2

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?

Community
  • 1
  • 1
Tea Bee
  • 401
  • 2
  • 8
  • 18
  • I have written a windows service that uses System.Drawing without any issues. The reason for the suggested prohibition is only if you are drawing to the desktop... in other words, a Windows Service should not try to draw to the screen, because a Windows Service does not necessarily have a logged in user, and therefore no desktop to draw to. – Nick Jan 26 '10 at 14:11
  • In fact it is explained in MSDN that you "can" use system.drawing in Windows services but they don't guarantee its behavior. http://forums.asp.net/t/1125885.aspx My service is running with no problems for few hours, processing few thousands of images but then this exception happens. – Tea Bee Jan 26 '10 at 14:21

4 Answers4

1

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
  • 5,364
  • 1
  • 27
  • 47
  • Good point, my trained mind has trouble imagining such a thing could be done. :) – ChaosPandion Jan 26 '10 at 14:08
  • 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 – Tea Bee Jan 26 '10 at 14:14
  • 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 Jan 26 '10 at 14:20
0

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
  • 77,506
  • 18
  • 119
  • 157
  • 1
    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. – Tea Bee Jan 26 '10 at 14:08
0

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.

  • 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 – Tea Bee Jan 26 '10 at 14:10
  • 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 –  Jan 26 '10 at 14:56
  • Aaah, missed that. I saw "task manager" and immediately raged. My bad. –  Jan 26 '10 at 15:26
  • @Will: The error->exception conversion for these components is definitely buggy, they throw OutOfMemoryException for all kinds of non-memory errors. – Ben Voigt Aug 11 '14 at 00:38
0

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'.)