加载大量图像会导致内存不足

时间:2014-11-06 18:22:26

标签: c# gdi

我发誓我知道这个问题的答案,但我忘记了。

我有这个功能。它加载位图并绘制它们。它可以快速连续调用。在大约300个位图之后,应用程序崩溃并发生System.OutOfMemoryException。

请告诉我我又做错了什么:)

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

2 个答案:

答案 0 :(得分:3)

根据Image.FromFile的文档,如果位图采用未知格式,则可以获得OutOfMemoryException。确保您的应用程序可以安全地加载您尝试使用的所有图像,并查看它是否始终在同一图像上崩溃。

如果它始终是相同的图像,那么您可以尝试以支持的像素格式(使用Photoshop或Paint.Net或其他一些免费工具)重新保存图像 - 这应该可以修复破坏您的特定图像应用

此外,在绘图逻辑周围添加一个异常处理程序,以确保应用程序在遇到错误图像时不会崩溃 - GDI +仅支持相对较少的图像格式。

要验证您是否实际耗尽内存(即,如果存在泄漏),请在应用程序运行时监视内存使用情况。如果你看到内存泄漏的迹象,你的问题可能在其他地方。

修改

阅读这些问题/解答,了解有关使用Image.FromStream而不是FromFile()的建议 - 这样做可以避免长时间锁定文件:

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

答案 1 :(得分:1)

这可能无法解决您的问题,但Image类实现了IDisposable。这意味着您可以将它包装在USING语句中,这会导致内部对象超出范围更快/更少的对象幸存到L2垃圾收集(它不应该在使用与调用dispose之间包装内容之间产生差异,但我们通过内存分析发现它实际上是这样做的。

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