views:

341

answers:

4

Hi, I am getting in out of memory exception while using system.drawing intensively in my windows service.

here is a part of my code:

FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
img = (Image)Image.FromStream(fs).Clone();

The exception is not only raised in this point, it is also raised in other points sometimes where it involves drawing, cropping, resizing, image copy

I am always disposing all the used objects.

I saw this article about the "Out of memory exception" in system.drawing here

and while it is very similar to my case it is different because my testing data is a repeated chain of 40 images, so if there is an issue in one of them it should appear quickly from the first cycle.

I saw the limitation mentioned here

it says that we should not use system.drawing on Win/Web services.

OK, I need to use it with a windows service for massive images processing, what are the alternatives if any?

A: 

Why are you cloning the image? In your example your are reading the data from the file and then creating a copy. It doesn't take much to throw an out of memory exception in a service with high object throughput.

You could simply do this:

var img = Image.FromFile(ImagePath);
ChaosPandion
I am disposing the Stream right after that code, if I don't clone it then disposing the stream will make the image Null too.I cant use Image.FromFile because it holds the file during the entire processing, it means that it cant be moved or deleted during the processing, this is not accepted in my case.
TB
A: 

You're using too much memory too fast, and probably not releasing it as soon as possible.

You need to refactor your code to be more conservative with your resources, and make sure you're not holding onto large objects longer than needed and that you are disposing of your IDisposables at the earliest time.

This process is not easy, nor can it be fully answered in a forum like this.

Will
I cant see that much of memory usage in the performance counters or the task manager, yes I am using large amount of memory but I don't think it is huge enough to cause this exception unless system.drawing classes are using more memory than expected
TB
You're not using much memory but you're getting OOM exceptions. Something doesn't jibe here. There isn't anything weird going on; these parts of the operating system (native drawing code) and CLR/GC aren't buggy. You need to drop all assumptions, start from scratch and triple check everything. Oh, and Task Manager sucks. At least grab Process Explorer from Sysinternals, and use PERFORMANCE COUNTERS http://msdn.microsoft.com/en-us/magazine/cc163491.aspx and http://msdn.microsoft.com/en-us/magazine/cc163528.aspx
Will
I mentioned that I am using Performance counters :)
TB
Aaah, missed that. I saw "task manager" and immediately raged. My bad.
Will
+1  A: 

The Image object you are calling Clone on isn't disposed (and maybe there are other similar mistakes in your code). The memory consumed by such objects is only released after the finalizer is run, which needs at least 2 GC cycles and the OutOfMemoryException might very well be thrown on the first GC.
Correctly disposing it should look similar to this:

FileStream fs = new FileStream(ImagePath, FileMode.Open, FileAccess.Read);
using(var tmp = Image.FromStream(fs))
  img = (Image)tmp.Clone();
// dispose fs an img after use like usually

Alternatively you could read the entire file into a MemoryStream and pass it to Image.FromStream - this means the image isn't parsed twice which should save additional resources.

Pent Ploompuu
Good point, my trained mind has trouble imagining such a thing could be done. :)
ChaosPandion
you mean the object called "img" ??? I am disposing it after finishing processing. I am also disposing the stream right after this code. if I dont call clone() then disposing the stream will make the image Null.check this question that I posted before:http://stackoverflow.com/questions/1951813/image-in-memory-compression-exception-when-getting-byte-array-from-the-image
TB
I mean the object created by the `FromStream(fs)` call (the one you are cloning) - disposing the stream doesn't dispose the created `Image` object.
Pent Ploompuu
A: 

This may not be relevant but...

I have had problems working with bitmaps in C++, getting out-of-resource errors from the lower-level windows APIs. It appears to result from the windows internal resource heap not being able to handle/allocate bitmaps/bitmap-sections when drawing is being done with bitblts and the like.

Don't know if something like this further down in the chain could be tripping the dotnet libraries. There is a tool somewhere on MSDN that installs a device driver and can be used to examine the various desktop heaps (don't know how that may relate to services.) I think (been a while since I used it) it shows percentages used/available - while that can be some indicator, I suspect fragmentation of those areas can also occur resulting the errors - unfortunately I have not been able to totally eliminate my problems, but that tool might help you diagnose yours. (Looks like the tool might be called 'dheapmon'.)

anon coward