0

I swear I knew the answer to this one but I forgot.

I have this function. It loads bitmaps and draws them. it can be called in rapid succession. After about 300 or so bitmaps the application crashes with a System.OutOfMemoryException.

Please tell me what am I doing wrong again :)

    private void PaintPicture()
    {
        string FullPath = Global.RunttimePath + EditType.FilePath;

        if (File.Exists(FullPath))
        {
            Image i = Image.FromFile(FullPath);
            //DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
            i.Dispose();
            //GC.Collect(); //I know I know... I should never call GC. So disabled it :) 
        }
        else
        {
            //DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
        }
    }
user2888973
  • 583
  • 3
  • 15
  • 1
    You have done nothing wrong in your example code, either the source of your problem is elsewhere and this code is just the "Straw that broke the camels back" or the problem is in code you removed to post your question here on SO. – Scott Chamberlain Nov 06 '14 at 18:26
  • Images are GDI resources and no GC'd anyway. – TaW Nov 06 '14 at 18:38

2 Answers2

4

According to the documentation of Image.FromFile you can get an OutOfMemoryException if the bitmap is in an unknown format. Make sure your application can safely load all images you're trying to use and see if it always crashes on the same image.

If it's always the same image then you can try re-saving the image in a supported pixel format (using Photoshop or Paint.Net or some other free tool) - this should fix the particular image that breaks your application.

Also, add an exception handler around your drawing logic to make sure your application doesn't crash when it runs into a bad image - GDI+ only supports a relatively low number of image formats.

To verify if you're actually running out of memory (that is, if there is a leak), monitor memory use while your application is running. If you see signs of a memory leak, your problem is likely elsewhere.

Edit:

Read these questions / answers for advice about using Image.FromStream instead of FromFile() - doing so avoids locking the file for a long time:

File.Delete failing when Image.FromFile was called prior it, despite making copy of loaded image and destroying original one

out of memory Image.FromFile

Community
  • 1
  • 1
xxbbcc
  • 16,930
  • 5
  • 50
  • 83
  • Oh Well... I know.. I should have checked this. 12 out of 4623 images got corrupted somehow. Due to the threaded loader I am implementing it crashed on either of those. Thanks for everyone's help :) – user2888973 Nov 06 '14 at 19:03
  • @user2888973 I know how that is, I ran into similar issues in the past. It's hard to spot bad images in a huge folder. – xxbbcc Nov 06 '14 at 19:06
  • @user2888973 I added a link that explains why `FromStream()` is better than `FromFile()`. – xxbbcc Nov 06 '14 at 19:09
  • @xxbbcc: Read which question&answers? – TaW Nov 07 '14 at 05:34
  • @TaW I'm sorry, I thought I added the link. Now I added 2 for sure. :) – xxbbcc Nov 07 '14 at 15:31
1

This likely won't resolve your problem, but the Image class implements IDisposable. That means you can wrap it in a USING statement, which causes the objects inside to go out of scope faster/less objects surviving to L2 garbage collection (it shouldn't make a difference between wrapping things in a using vs. calling dispose, but we found through memory profiling that it actually does).

if (File.Exists(FullPath))
    {
        using(Image i = Image.FromFile(FullPath))
        {
            DrawImage(i, pnlPicture, pbColor.BackColor); //I disabled this so the problem is not here
            //GC.Collect(); //I know I know... I should never call GC. So disabled it :) 
        }
    }
    else
    {
        //DrawImage(Properties.Resources.Fail800, pnlPicture, Color.White, true);
    }
}
DVK
  • 2,726
  • 1
  • 17
  • 20