FileStream doesn't release resources
-
Tuesday, August 22, 2006 10:45 AMI 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?
Answers
-
Tuesday, August 22, 2006 1:17 PM
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.
All Replies
-
Tuesday, August 22, 2006 10:59 AMfirst close then dispose
-
Tuesday, August 22, 2006 11:02 AMstill throws the exception
-
Tuesday, August 22, 2006 11:24 AMI 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(); -
Tuesday, August 22, 2006 11:49 AMModerator
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 StawskiMVP Saturday, April 04, 2009 4:20 AM
-
Tuesday, August 22, 2006 11:56 AM
just for testing, try adding a small delay after first dispose line.
system.threading.thread.sleep(300)
-
Tuesday, August 22, 2006 1:17 PM
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:55 PMModerator
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 2:28 PMi 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:33 PMThank 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.
-
Monday, June 11, 2007 12:14 AMHow could i use appels idea to create a bitmap?
-
Tuesday, June 03, 2008 2:25 PMIsn't there a way to force a release on these types of resources?
Thank you.
Nikos- Edited by Nikos_Y Tuesday, June 03, 2008 2:36 PM corrected my question
-
Saturday, April 04, 2009 4:20 AM
nobugz proposal really worked for me. I wonder whether this is like this by design or if there is a problem
-
Saturday, April 04, 2009 1:17 PMModeratorI'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. -
Monday, July 06, 2009 2:30 AM
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 09, 2009 9:22 PM
-
Monday, July 06, 2009 5:40 PMWell, 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 06, 2009 5:42 PM added more info about disposing the image.
-
Monday, July 06, 2009 6:13 PMOk, 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
-
Friday, October 09, 2009 9:23 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! -
Saturday, January 23, 2010 4:33 PMthanks!
-
Monday, February 08, 2010 11:41 AMMY 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 ? -
Thursday, April 29, 2010 4:56 AM
thanks NoBugz
that fixed one wildly buggy app
-
Sunday, April 03, 2011 6:19 PMThanks Appel. (& NoBugz)

