none
FileStream doesn't release resources

    Question

  • I have an application that is creating a number of images. After they have been created I try to FTP them to my webserver. This is done essentially by:

    Each image is saved by:
    1. Create a filestream
    System.IO.FileStream fs = new System.IO.FileStream(Path + FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);

    2. Save the image
    Image.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg);

    3. Close the filestream
    fs.Dispose()
    fs.Close();

    Now, when i try to send them to my webserver, i use a class that opens a filestream by
    input = New FileStream(FileName, FileMode.Open)

    But this produces an exception:
    IOException
    The process cannot access the file '<filename>' because it is being used by another process.

    If i create the images, restart the application and then tries to send them by ftp everything works fine, which must mean that the initial filestream, which were used for creating the images, doesn't release the file.


    Shouldn't FileStream.Dispose() and FileStream.Close() release any resources?
    Tuesday, August 22, 2006 10:45 AM

Answers

  • Close and Dispose are the same for Stream and any class that inherits from it. So you only need to either call Close or Dipose although the second call is simply ignored so it doesn't really matter if you call both.



        using (FileStream fs = new FileStream(@"c:\temp\somefile.dat", FileMode.Create))
        {
         // Write some content to the created file
        }

     

    Does the simplified example throw the exception? If so I'd start looking for tools like antivirus software or desktop search tools to blame. Using FileMon or similiar tools is one way to try and find out what's going on.

    Tuesday, August 22, 2006 1:17 PM

All replies

  • first close then dispose
    Tuesday, August 22, 2006 10:59 AM
  • still throws the exception
    Tuesday, August 22, 2006 11:02 AM
  • I believe it actually boils down to the question why this throws the exception:

    FileStream fs = new FileStream(Path + FileName, FileMode.Create, FileAccess.Write);
    fs.Close();
    fs.Dispose();

    FileStream fs2 = new FileStream(Path + FileName, FileMode.Open);
    fs2.Close();
    fs2.Dispose();
    • Proposed as answer by so2day Monday, December 24, 2012 1:11 PM
    • Unproposed as answer by so2day Monday, December 24, 2012 1:11 PM
    Tuesday, August 22, 2006 11:24 AM
  • I've ran into this problem a few times but I could never really nail down what caused it.  It tended to disappear when mucking with the code.  What's clear to me is that the Image and/or Bitmap class leave a file handle open after the bitmap is loaded.  Code like this will always fail with a "generic error" exception:

        Dim bmp As Image = Bitmap.FromFile("c:\temp\test2.bmp")
        bmp.Save("c:\temp\test2.bmp")

    And this code works:

        Dim bmp As Image = Bitmap.FromFile("c:\temp\test2.bmp")
        Dim cpy As New Bitmap(bmp)
        bmp.Dispose()
        cpy.Save("c:\temp\test2.bmp")

    The Dispose call is critical, that seems to actually close the file handle.
    • Proposed as answer by Jonas Stawski Saturday, April 4, 2009 4:20 AM
    Tuesday, August 22, 2006 11:49 AM
    Moderator
  • just for testing, try adding a small delay after first dispose line.

    system.threading.thread.sleep(300)

    Tuesday, August 22, 2006 11:56 AM
  • Close and Dispose are the same for Stream and any class that inherits from it. So you only need to either call Close or Dipose although the second call is simply ignored so it doesn't really matter if you call both.



        using (FileStream fs = new FileStream(@"c:\temp\somefile.dat", FileMode.Create))
        {
         // Write some content to the created file
        }

     

    Does the simplified example throw the exception? If so I'd start looking for tools like antivirus software or desktop search tools to blame. Using FileMon or similiar tools is one way to try and find out what's going on.

    Tuesday, August 22, 2006 1:17 PM
  • I agree with nobugz

    I actually had the same issue and he had responded and we agreed that it is most likely the Image/Bitmap not releasing the handle quick enough. hopefully a fix in SP1 next month :-)

    its nothing to do with the filestream but the Bitmap object not releasing the resources quick enough. Even adding a delay wouldn't help much

    Tuesday, August 22, 2006 1:55 PM
    Moderator
  • i tried to delay the thread after creating the files but that didn't help. I have also tried to do use Bitmap.Dispose() but that didn't help either. And i know it's the application that blocking the file because if i skip creation and only transferred the files it works fine.

    Is there no way i can force a release of all resources of the file?
    Tuesday, August 22, 2006 2:28 PM
  • Thank you appel. I tried your example and it worked perfectly, so far at least! It would be nice to know what actually causes this problem though.
    Tuesday, August 22, 2006 2:33 PM
  • How could i use appels idea to create a bitmap?
    Monday, June 11, 2007 12:14 AM
  • Isn't there a way to force a release on these types of resources? 
     Thank you.
     Nikos
    • Edited by Nikos_Y Tuesday, June 3, 2008 2:36 PM corrected my question
    Tuesday, June 3, 2008 2:25 PM
  • nobugz proposal really worked for me. I wonder whether this is like this by design or if there is a problem

    Saturday, April 4, 2009 4:20 AM
  • I've since find out this is by design.  GDI+ creates a memory mapped view of the file so it efficiently can read portions of the file without having to read it completely.  The Windows API functions involved with this are CreateFileMapping() and MapViewOfFile(), possibly CreateDIBSection().  Sadly, the minor optimization isn't exactly worth the price.

    A way to avoid it is to read the file into a MemoryStream first.  But that requires double the memory.
    Hans Passant.
    Saturday, April 4, 2009 1:17 PM
    Moderator
  • nobugz, thanks for a helpful tip!

    Your solution didn't work exactly for me because I didn't want to just save the image or bitmap; I needed to return the image as an image.  First, I tried image.Clone to make a new image and then dispose the original that was opened from a file.  That didn't seem to help - in fact, seem nothing, it didn't help.

    Then I went around the world with my image and it finally seems (seems because who knows what tomorrow will bring) to work.

    Image image = Image.FromFile(fileName);
    Bitmap bmp = new Bitmap(image);
    image.Dispose();
    return Image.FromHbitmap(bmp.GetHbitmap());
    
    I noticed that this issue is file specific for me.  I can run the application against about 3000 images and the same 5 or 6 images cause the error every time.  The first time I access them, it works correctly but I can close the app, re-open, and run again and the same 5 or 6 images fail every single time.  The only way to get it to work on those images again is to restore from my local working backup.  I haven't tried rebooting to see if it resets the lock since rebooting isn't a useful step in running my app. :)

    I've passed these files through a FAT32 folder to make sure that any lingering or different ACL or streams are removed.  The images are scanned images from my music CDs so I am sure of their source and their source is similar to the source of all the others that do work - unless there's some weird coincidence where those images came from one scanner/software package.  In any case, there's something in these files that GDI+ doesn't like.  And the problem follows copies of the same files onto different computers as well.

    This issue was identified at least in .Net 2 based on this thread and now we're at 3.5 SP1 and no fix.  :(

    Regards,

    Dale
    • Proposed as answer by mrssuper Friday, October 9, 2009 9:22 PM
    Monday, July 6, 2009 2:30 AM
  • Well, forget my round the world plan.  It is a major memory leak.  For every 4 to 5 MB image causes a 30MB memory leak!  And this includes the memory used after calling dispose on the returned image.

    I have to come up with a different way to solve this.  Any ideas would be appreciated.  nobugz solution would work except that I have to return an Image, not a Bitmap.

    Regards,

    Dale
    • Edited by Dale At Work Monday, July 6, 2009 5:42 PM added more info about disposing the image.
    Monday, July 6, 2009 5:40 PM
  • Ok, I should have known this from the start because I've done it before. I can return the Bitmap even though the method signature says Image because an Image is a Bitmap. Thanks again, nobugz, for the solution. Dale
    Monday, July 6, 2009 6:13 PM

  • Image image = Image.FromFile(fileName);
    
    Bitmap bmp = new Bitmap(image);
    
    image.Dispose();
    
    return Image.FromHbitmap(bmp.GetHbitmap());
    
    
    

    This solved my problem.. thank you so much!
    Friday, October 9, 2009 9:23 PM
  • thanks! 

    Saturday, January 23, 2010 4:33 PM
  • MY CODE IS below
    try{
    str = New System.IO.FileStream(DirPath & "\S1.bmp", FileMode.Open)

    pic1.Image = Image.FromStream(str)

                str.Close()
    }
    catch (ex as excaption)
    {
    ....'message
    }
    end try

    The above code misbehave, some times not working ...

    i have tried  for open it create ,write mode but not in result ...
    even i apply for delay ....

    what i have to do ?
    Monday, February 8, 2010 11:41 AM
  • thanks NoBugz

    that fixed one wildly buggy app

    Thursday, April 29, 2010 4:56 AM
  • Thanks Appel. (& NoBugz)
    Sunday, April 3, 2011 6:19 PM