Results 1 to 19 of 19

Thread: [RESOLVED] Deletion of current image impossible as it is being used by another process

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Resolved [RESOLVED] Deletion of current image impossible as it is being used by another process

    Hello,

    I have a WindowsForm in VB.NET in which I display either a single image or a slide show of images.

    When I delete an image which is in a slideshow it works fine, because I first select the next image and then delete the old image.

    Whenever I have a solitary image however there is a problem, because I cannot delete the image as long it is displayed by the PictureBox.

    Therefore I first load another image (from My.Resources) and then Refresh(), dispose of the oldImage, set the oldImage to Nothing and still get the error

    System.IO.IOException: 'The process cannot access the file 'D:\OneDrive\Afbeeldingen\Schermafbeeldingen\2016-10-03 (0) - Copy_R.png' because it is being used by another process.'

    Any other suggestions?

    Name:  PV_FileUsed.jpg
Views: 3025
Size:  31.0 KB

    Code:
    Private Sub DoDelete()
            StrOrgFile = PictureBox1.ImageLocation
            If StrOrgFile = "" Then Exit Sub
    
            Dim oldImage As Image = PictureBox1.Image
            Dim Response As Long = MsgBox("Are you sure you want to delete this image?", 32 + 4, "Delete?")
    
            If Response = vbYes Then
                BlnDelete = True
                StrStartInFolder = GetTextFromFile(SettingsPath, 0, StrErr)
    
                ' In case a single picture is displayed, StrStartInFolder = "",
                ' else it is in a FolderPath and another image is loaded before the oldImage is deleted
                If StrStartInFolder = "" Or StrStartInFolder = "0" Then
    
                    'Display different image in PictureBox1
                    PictureBox1.Image = My.Resources.startpage_l
                    Refresh()
    
                    'New image is displayed so I suppose I can delete the old one
                    oldImage.Dispose()
                    oldImage = Nothing
    
                    System.IO.File.Delete(StrOrgFile)
                    'Kill(StrOrgFile)
                    'SafeFileDelete(StrOrgFile)
    
                    'System.IO.IOException 'The process cannot access the file _
                    'D:\OneDrive\Afbeeldingen\Schermafbeeldingen\2016-10-03 (0) - Copy_R.png' _
                    'because it Is being used by another process.'
    
                    Exit Sub
                Else
    Grtz Bart

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Deletion of current image impossible as it is being used by another process

    .Net locks the file so that it has the option of using the file as a backing store for the image if it needs to release memory. It can then reload the image from the disk as needed. Getting it to release the file is somewhat challenging.

    Generally, if I needed to do that, I would only load the image from the file temporarily, then draw a copy of it to a bitmap, release the file, and use the bitmap in the picturebox. Something along the lines of this test example.
    Code:
      Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim b1 As Image = Image.FromFile("c:\c\pumpgages.png")
        Dim b2 As New Bitmap(b1.Width, b1.Height)
        Using g As Graphics = Graphics.FromImage(b2)
          g.DrawImage(b1, 0, 0)
        End Using
        PictureBox1.Image = b2
        b1.Dispose()
      End Sub
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by passel View Post
    .Net locks the file so that it has the option of using the file as a backing store for the image if it needs to release memory. It can then reload the image from the disk as needed. Getting it to release the file is somewhat challenging.

    Generally, if I needed to do that, I would only load the image from the file temporarily, then draw a copy of it to a bitmap, release the file, and use the bitmap in the picturebox. Something along the lines of this test example.
    Code:
      Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim b1 As Image = Image.FromFile("c:\c\pumpgages.png")
        Dim b2 As New Bitmap(b1.Width, b1.Height)
        Using g As Graphics = Graphics.FromImage(b2)
          g.DrawImage(b1, 0, 0)
        End Using
        PictureBox1.Image = b2
        b1.Dispose()
      End Sub
    ThnX Passel for your suggestion.

    I tried it but still have the same error when I delete... something else seems to hold up the original file.

    Name:  PV_FileUsed2.jpg
Views: 2820
Size:  10.4 KB

    This is the code:

    Code:
        Private Sub LoadImage(StrImgPath As String)
            Dim b1 As Image = Image.FromFile(StrImgPath)
            Dim b2 As New Bitmap(b1.Width, b1.Height)
            b2.GetPropertyItem()
    
            Using g As Graphics = Graphics.FromImage(b2)
                g.DrawImage(b1, 0, 0)
            End Using
            PictureBox1.ImageLocation = ""
            PictureBox1.Image = b2
            Refresh()
            b1.Dispose()
        End Sub
    
        Private Sub DoDelete()
            StrOrgFile = PictureBox1.ImageLocation
            If StrOrgFile = "" Then Exit Sub
            LoadImage(StrOrgFile)
    
            Dim Response As Long = MsgBox("Are you sure you want to delete this image?", 32 + 4, "Delete?")
    
            If Response = vbYes Then
                BlnDelete = True
                StrStartInFolder = GetTextFromFile(SettingsPath, 0, StrErr)
    
                ' In case a single picture is displayed, StrStartInFolder = "",
                ' else it is in a FolderPath and another image is loaded before the oldImage is deleted
                If StrStartInFolder = "" Or StrStartInFolder = "0" Then
    
                    'Display different image in PictureBox1
                    PictureBox1.Image = My.Resources.startpage_l
                    Refresh()
                    System.IO.File.Delete(StrOrgFile)
                    'SafeFileDelete(StrOrgFile)
                    Exit Sub
                Else
                    Dim di As New DirectoryInfo(StrStartInFolder)
                    ArrFi = di.GetFiles("*")
                    If q = 0 Then
                        GetFileUp()
                    ElseIf q = -1 Then
                        GetFileDown()
                    Else
                        MsgBox("No q")
                    End If
                End If
            Else
                BlnDelete = False
            End If
            BlnDelete = False
            Exit Sub
    noDelete:
            MsgBox("You can not delete this image, try deleting it in a 'Browse folder' view.")
            BlnDelete = False
    
        End Sub

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Deletion of current image impossible as it is being used by another process

    It's amazing how tenacious System.Drawing is in keeping its grubby grip on the image. After some experimentation, however, I found a more concise way to do it:

    Code:
            Dim img As Image = Image.FromFile(filename)
            PictureBox1.Image = New Bitmap(img)
            img.Dispose()
    
            'and now this works!
            IO.File.Delete(filename)
    But it doesn't work if you comment out the Dispose statement (or Using ... End Using). I wonder why...?

    BB

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by boops boops View Post
    It's amazing how tenacious System.Drawing is in keeping its grubby grip on the image. After some experimentation, however, I found a more concise way to do it:

    Code:
            Dim img As Image = Image.FromFile(filename)
            PictureBox1.Image = New Bitmap(img)
            img.Dispose()
    
            'and now this works!
            IO.File.Delete(filename)
    But it doesn't work if you comment out the Dispose statement (or Using ... End Using). I wonder why...?

    BB
    Hi BB,

    Regretably not yet:

    Name:  PV_FileUsed3.jpg
Views: 2709
Size:  15.7 KB


  6. #6
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Deletion of current image impossible as it is being used by another process

    Hi BartH,

    I hadn't looked at your code because my reply was meant as a footnote to Passel's recommendation. I wasn't offering you a method you can simply paste into your present code.

    Passel's code in the LoadImage sub is fine; my suggested method is just more compact. It leaves you free to delete the file in the DoDelete sub or wherever you like. But in DoDelete you are now unnecessarily reloading the image, not once but twice! Probably that is what is causing the problem. You could just delete the first 6 lines in DoDelete (post #6). Or, better, just keep a line of code to check that the file exists before you delete it.

    BB

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by boops boops View Post
    Hi BartH,

    I hadn't looked at your code because my reply was meant as a footnote to Passel's recommendation. I wasn't offering you a method you can simply paste into your present code.

    Passel's code in the LoadImage sub is fine; my suggested method is just more compact. It leaves you free to delete the file in the DoDelete sub or wherever you like. But in DoDelete you are now unnecessarily reloading the image, not once but twice! Probably that is what is causing the problem. You could just delete the first 6 lines in DoDelete (post #6). Or, better, just keep a line of code to check that the file exists before you delete it.

    BB
    Thanks for clarifying BB,

    I did test various variations and will look again tomorrow and set up an isolated test case.
    I am curious: how could I test if the file is used by another process, apart from trying to delete it and find that doesn't work...

    Grtz Bart

  8. #8
    Fanatic Member
    Join Date
    Aug 2004
    Location
    Essex, UK
    Posts
    750

    Re: Deletion of current image impossible as it is being used by another process

    I don't want to take this off at a tangent but I thought the usual error message when an image file was locked was something like "A generic error occurred in GDI+" - unless this has changed in later versions of VS. I wonder if the use of Onedrive here is significant?

    This is my method of opening an image so the file is not locked:
    Code:
    ' Open new image using FileStream so file is not locked
    Using fs As FileStream = New FileStream(filename, FileMode.Open)
        Dim bm As Bitmap = CType(Image.FromStream(fs), Bitmap)
        PictureBox1.Image = bm
    End Using

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Deletion of current image impossible as it is being used by another process

    Code:
    Private Sub DoDelete()
            StrOrgFile = PictureBox1.ImageLocation
    The above line should be meaningless with what I intended.
    You must still be assigning the file to the picturebox somewhere.
    There should be no ImageLocation as I intended that you assign a bitmap to the picturebox and draw in it. The picturebox should have no association with a file.

    If you need to associate the file path of the image stored in the picturebox, you can either track that separately somehow, or assigin it to the .Tag property of the picturebox, where it is just associated data, not a reference to the image as far as the picturebox is concerned.
    Last edited by passel; Feb 21st, 2020 at 05:28 PM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  10. #10
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by paulg4ije View Post
    I don't want to take this off at a tangent but I thought the usual error message when an image file was locked was something like "A generic error occurred in GDI+" - unless this has changed in later versions of VS. I wonder if the use of Onedrive here is significant?

    This is my method of opening an image so the file is not locked:
    Code:
    ' Open new image using FileStream so file is not locked
    Using fs As FileStream = New FileStream(filename, FileMode.Open)
        Dim bm As Bitmap = CType(Image.FromStream(fs), Bitmap)
        PictureBox1.Image = bm
    End Using
    The pattern is becoming clear. Our 'methods' are really similar to Passel's:

    1. Get the image from a file (Passel's b1, your FileStream, my Image.FromFile).
    2. Copy the image from step 1 (Passel's b2, your Image.FromStream, my New Bitmap(image)
    3. Dispose of the first image (b1.Dispose, End Using, my img.Dispose). This breaks the link with the file.

    Actually, I normally prefer Using..End Using blocks to Dispose statements, because they emphasize the temporary lifespan of the object.

    As for the error messages in System.Drawing, it wouldn't surprise me if they have upgraded the messages in later Framework versions. From useless garbage to unhelpful gibberish.

    BB

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: Deletion of current image impossible as it is being used by another process

    Why are you using ImageLocation in such a weird way? Just set the ImageLocation to the path of the file. That's it, that's all. Doing so does not lock the file so you can do whatever you want to that file.

  12. #12

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: Deletion of current image impossible as it is being used by another process

    Hi jmcilhinney,

    That was what I started off with, but it resulted in not being able to delete the displayed image (even after the PictureBox was fed a new image).

    The current status is that it all works as desired with loading the images with

    Code:
    Using fs As FileStream = New FileStream(filename, FileMode.Open)
        Dim bm As Bitmap = CType(Image.FromStream(fs), Bitmap)
        PictureBox1.Image = bm
    End Using
    in ordert o be able to delete it with

    Code:
                    Dim img As Image = Image.FromFile(StrOrgFile)
                    img.Dispose()
                    Refresh()
                    File.Delete(StrOrgFile)

  13. #13
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by BartH_NL View Post
    That was what I started off with, but it resulted in not being able to delete the displayed image (even after the PictureBox was fed a new image).
    You're trying to fix the wrong problem. If you explain what the actual issue was when using ImageLocation as it was intended then I'm confident that we can provide a solution for that.

  14. #14
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Deletion of current image impossible as it is being used by another process

    I haven't worked with the ImageLocation property before, but it works as jmcilhinney says.
    If you use the Load method, that will update ImageLocation but will also lock the file.
    If you just set ImageLocation directly, it must load a copy of the image, and you can then do what you want with the file, even including deleting the file.
    Deleting the file will not affect the copy that is showing in the picturebox, but of course you can't reload it later, if you've deleted the file.

    So, a quick test that just sets the ImageLocation to two different file paths, or sets it to a null string seems to work fine for displaying or not displaying an image in the picturebox.
    Code:
    Public Class Form1
    
      Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        PictureBox1.ImageLocation = "c:\c\pumpgages1.png"
      End Sub
    
      Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
        PictureBox1.ImageLocation = "c:\c\wrappedCase1.png"
      End Sub
    
      Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
        PictureBox1.ImageLocation = ""
        ' IO.File.Delete("c:\c\pumpgages1.png")
      End Sub
    End Class
    Likewise, uncommenting the File.Delete line (and commented out setting ImageLocation to ""), tested the fact that I could hit button1, loading the image, and then button3,deleting the source file of the image, without affecting the displayed image (and proving the file was not locked). I also manually renamed the files while they were displayed, which is what I originally did to see that they were locked before, and I had no issues renaming the file after it was loaded by setting ImageLocation.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  15. #15

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Thumbs up Re: Deletion of current image impossible as it is being used by another process

    ThanX a lot, Passel and jmcilhinney,

    I was already going to test it all over today, but the last post of Passel describes the solution perfectly.

    I set up this: (make sure you adjust the image locations - use copies as the images are going to be deleted)

    Code:
    Public Class Form3
    
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
            On Error GoTo ErrMsg
            PictureBox1.Load("C:\T\IMG_1.JPG")
            If MsgBox("Delete image?", 4) = vbYes Then
                'PictureBox1.Image.Dispose() - not applicable here
                PictureBox1.ImageLocation = ""
                IO.File.Delete("C:\T\IMG_1.JPG")
            End If
            Exit Sub
    ErrMsg:
            MsgBox(Err.Description, 16, "Err: " & Err.Number)
        End Sub
    
        Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
            On Error GoTo ErrMsg
            PictureBox1.Image = Image.FromFile("C:\T\IMG_2.JPG")
            If MsgBox("Delete image?", 4) = vbYes Then
                PictureBox1.Image.Dispose()
                PictureBox1.Image = Nothing
                IO.File.Delete("C:\T\IMG_2.JPG")
            End If
            Exit Sub
    ErrMsg:
            MsgBox(Err.Description, 16, "Err: " & Err.Number)
        End Sub
    
        Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
            On Error GoTo ErrMsg
            PictureBox1.ImageLocation = "C:\T\IMG_3.JPG"
            If MsgBox("Delete image?", 4) = vbYes Then
                'PictureBox1.Image.Dispose() - not applicable here
                PictureBox1.ImageLocation = ""
                IO.File.Delete("C:\T\IMG_3.JPG")
            End If
            Exit Sub
    ErrMsg:
            MsgBox(Err.Description, 16, "Err: " & Err.Number)
        End Sub
    
    End Class
    Name:  PV_T.jpg
Views: 2785
Size:  22.2 KB

    Conclusions:
    PictureBox.Load loads the file from fullname but also locks the file, if file is missing - error, delete - error because locked
    PictureBox.Image locks and accepts the file as Image object, if file is missing - error, delete - if Image.Dispose() is used no problem (else error because locked)
    PictureBox.ImageLocation does not lock and takes file fullname as String, if file is missing - no error (displays missing file icon), delete no problem

    Last edited by BartH_NL; Feb 22nd, 2020 at 06:35 PM.

  16. #16

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: Deletion of current image impossible as it is being used by another process

    Additional comment:

    I noticed that when I add the images to the PictureBox with CType(Image.FromStream(fs), Bitmap), in time the resources get all taken up, so the application runs into troubles when the 4GB treshold is reached.

    Code:
        Using fs As FileStream = New FileStream(OpenFileDialog1.FileName, FileMode.Open)
            Dim bm As Bitmap = CType(Image.FromStream(fs), Bitmap)
            PictureBox1.Tag = OpenFileDialog1.FileName
            PictureBox1.Image = bm
            BlnIsStart = False
        End Using
    I solved this by abandoning the consept of using a dummy image so the original image can be disposed of (when needed) and using ImageLocation instead.
    Apparently the copied images keep taking up memory.

    Name:  PV_FileUsed_Overload.jpg
Views: 2683
Size:  24.2 KB

  17. #17
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Deletion of current image impossible as it is being used by another process

    In order to not have to test to see if there is an image in the picturebox before I dispose of it, at startup I create a small empty bitmap and assign it to the picturebox.
    Then each time I updated the picturebox from a memory stream, I disposed the existing image. I was displaying 100's of Gigabytes worth of images over the course of a single day, and I know the applications ran for weeks or months without issue.
    I think if you added a line to the code you posted, it probably would have fixed the issue.
    Code:
        Using fs As FileStream = New FileStream(OpenFileDialog1.FileName, FileMode.Open)
            Dim bm As Bitmap = CType(Image.FromStream(fs), Bitmap)
            PictureBox1.Tag = OpenFileDialog1.FileName
            PictureBox1.Image.Dispose()   'dispose of the old image before assigning a new image
            PictureBox1.Image = bm
            BlnIsStart = False
        End Using
    You didn't realize while the local reference to the bitmap (bm) is temporary, you copy that reference to the Picturebox1.Image, so the bitmap isn't temporary, it is reference by the picturebox. And then you clobber that reference the next time without cleaning up the resources, so resource leak...

    p.s. I guess in an earlier case I didn't preset the picturebox with an empty bitmap, so just tested each time, but I think that is less optimal. This is the actual code that was in that program.
    Code:
          With PictureBox1
            If .Image IsNot Nothing Then .Image.Dispose() 'If we have an image in the picturebox, dispose of it first
            .Image = New Bitmap(mstream)                  'Create a new image from the memorystream provided by the TCP receiver
          End With
    Last edited by passel; Feb 27th, 2020 at 01:03 AM.
    "Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930

  18. #18
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,297

    Re: Deletion of current image impossible as it is being used by another process

    Quote Originally Posted by passel View Post
    In order to not have to test to see if there is an image in the picturebox before I dispose of it, at startup I create a small empty bitmap and assign it to the picturebox.
    Then each time I updated the picturebox from a memory stream, I disposed the existing image.
    Or, if you're using a VB version that supports them, use a null-conditional operator, i.e.
    vb.net Code:
    1. PictureBox1.Image?.Dispose()

  19. #19

    Thread Starter
    Junior Member
    Join Date
    Feb 2020
    Posts
    22

    Re: [RESOLVED] Deletion of current image impossible as it is being used by another pr

    Hello Passel and jmcilhinney,

    I took a little while before I had the chance to look into your comments, thanx for pointing this out to me.

    @Passel:
    I understand what you mean - I can smack my head as I have been using .Image.Dispose() before, just hadn't thought of it now I needed it 8-[

    @jmcilhinney:
    That's interesting - next level - using null-conditional operators makes much cleaner code!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width