Bitmap ArgumentException after returning in using statement

726 views Asked by At

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

2

There are 2 answers

0
Ravand On BEST ANSWER

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.

7
Dark Falcon On

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);
    }
}