1

So I am currently working on an image resizer which works/worked pretty fine but with the exception that it gave me an OutOfMemoryException when I was processing too many images at once crashing the program.

So in order to fix that I have wrapped the methods inside a using statement so the Bitmaps can be disposed correctly.

However I noticed that if I am returning my Bitmap inside the using statement I get this "ArgumentException was unhandled" message

Here my ImageResize method:

 public Bitmap ResizeImage(MemoryStream ms, Size size)
    {
        if (comboBox2.Text == "Pixel")
        {
            using (Bitmap img = new Bitmap(new Bitmap(ms, true), size.Width, size.Height))
            {
                var original = new Bitmap(ms, true);
                Graphics graphic = Graphics.FromImage(img);

                //IRRELEVANT CODE.....

                return img;
            }
        }
        else
        {
            return null;
        }

And here when i try to save my image outside the ImageResize method:

private void button1_Click(object sender, EventArgs e)
    {
    //IRRELEVANT CODE ...
    img = ResizeImage(memory, new Size(getX(), getY()));
    //IRRELEVANT CODE ...
    img.Save(outputFileName, codec, encoderParams); //<-Exception occurs here
    }

When I remove the using statement everything works perfectly fine again, however I have to use the using blocks to dispose the Bitmap and therefor to prevent the memory leak. Also when I save the image inside the using statement it works fine too, but that is not a solution in my case.

What am I doing wrong? To me it seems like the Bitmap is not returned correctly.

I appreciate any help and thanks in advance Ravand

wayzz
  • 585
  • 6
  • 23
Ravand
  • 39
  • 1
  • 11

2 Answers2

5

You put your using in the wrong place. After the end of the using block (which includes returning from it), the object controlled by the block is disposed. Accessing a disposed bitmap is an error.

Your using needs to be here instead:

private void button1_Click(object sender, EventArgs e)
{
    //IRRELEVANT CODE ...
    using(img = ResizeImage(memory, new Size(getX(), getY())))
    {
        //IRRELEVANT CODE ...
       img.Save(outputFileName, codec, encoderParams);
    }
}
Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • Provide more details about the not-so-irrelevant code, or simply limit how many images you process at a time. – Dark Falcon Nov 21 '14 at 13:22
  • Oh i'm sry i missread, i didn't get the MemoryException but i got the ArgumentException that i received in the button click event now in the ResizeImage method... so kind i'm kind of back to where i started – Ravand Nov 21 '14 at 13:38
  • 1. You removed the `using` in `ResizeImage`? 2. For what argument? – Dark Falcon Nov 21 '14 at 13:50
  • 1. Yes i put it back to how it was before 2. It happens when i initialize the bmp However i noticed that if i just use 1 image it works, but if i process many pictures it gives me this ArgumentException from the VS debugger, however if i run the executable file it tells me OutOfMemory instead of ArgumentException, maybe something gets mixed up there? – Ravand Nov 21 '14 at 13:57
  • One thing I noticed: You're using a `Graphics` object which needs to be in a using block, as it implements `IDisposable` also. That block would go inside `ResizeImage`. – Dark Falcon Nov 21 '14 at 14:18
  • I think i got it working now, i forgot to dispose the Graphics variable at the end of the ResizeImage method. I will test now with ridiculous image sizes EDIT: Just saw your reply your right it was because of the Graphics Thanks a bunch for your help – Ravand Nov 21 '14 at 14:23
  • Ok this seems to give me a little bit more space to do bigger files but it still throws a OutOfMemoryException when using multiple bigger files. I'm not sure where i have a memory leak now since im sure i have put everything in using statements – Ravand Nov 21 '14 at 14:31
0

Ok I finally fixed the problem with the memory leak, turned out that I was indeed releasing/disposing the images but it wasn't doing it quick enough which caused this outOufMemoryException when you were processing alot of very big images right after the other. I tried making everything multithreaded and always waiting for the WorkingSet to get smaller without success.

Turned out it was easier than I thhought, all I had to do is put this at the end of my resizing method:

GC.Collect();
GC.WaitForPendingFinalizers();
System.Threading.Thread.SpinWait(5000);

And this seems to do the magic for resizing big images with 10-20mb in size and with 10000x10000 for the resolution. Can somebody maybe explain why the SpinWait helps but not a normal thread sleep? Whenever I tried sleeping the thread it also seemed to sleep the releasing of the memory.

Ravand
  • 39
  • 1
  • 11