C#位图导致内存泄漏

时间:2015-12-09 08:07:43

标签: c# image memory-leaks bitmap garbage-collection

我有一个简单的应用程序,可以渲染图像并打印出来。为了方便设计,我使用了自定义Control

现在,我有一个简单的控制尺寸1800 x 2400(是的,相当大):

public class PhotoControl : UserControl
{
    public PhotoControl()
    {
        InitializeComponent();
    }
}

一个扩展类,用它来生成图像:

public static class PhotoProcessor
{
    private static readonly PhotoControl PhotoForm = new PhotoControl(); // Single instance

    public static Image GenerateImage(this Photo photo)
    {
        PhotoForm.SetPhoto(photo); // Apply a photo

        Image result;

        using (Bitmap b = new Bitmap(PhotoForm.Width, PhotoForm.Height))
        {
            Rectangle r = new Rectangle(0, 0, b.Width, b.Height);
            PhotoForm.DrawToBitmap(b, r); // Draw control to bitmap

            using (MemoryStream ms = new MemoryStream())
            {
                b.Save(ms, ImageFormat.Png); // Save bitmap as PNG
                result = Image.FromStream(ms); 
            }
        }

        // GC.Collect();
        // GC.WaitForPendingFinalizers();

        return result; // return
    }

现在,我尝试用这个来生成30张照片:

myPhoto.GenerateImage().Save(@"Output1.png", ImageFormat.Png);
myPhoto.GenerateImage().Save(@"Output2.png", ImageFormat.Png);

我不存储引用,我只保存图像并期望GC在保存到文件后收集这些图像。

大约需要2 GB的内存,最后抛出异常:

  

System.Drawing.dll中出现未处理的“System.OutOfMemoryException”类型异常

     

其他信息:内存不足。

如果我查看Visual Studio诊断工具,它看起来像:

enter image description here

让我们拍一张快照,看一下堆的内容,我们会看到有很多MemoryStream s:

enter image description here
enter image description here

是什么导致MemoryStream产生内存泄漏?据我所知,using()会生成Dispose()来电,应该对此进行处理。

P.S。如果我删除评论并调用GC.Collect(); GC.WaitForPendingFinalizers();,那么它需要的内存减少2-3倍,但它仍然会增长 - 约200张图像仍然会杀死一个应用程序。

将图像保存更改为以下内容:

Image img;

img = myPhoto.GenerateImage();
img.Save(@"Output1.png", ImageFormat.Png);
img.Dispose();

img = myPhoto.GenerateImage();
img.Save(@"Output2.png", ImageFormat.Png);
img.Dispose();

将产生与使用GC.Collect();相同的结果。它也会占用更少的内存,但不能消除内存泄漏。

1 个答案:

答案 0 :(得分:2)

Image实现IDisposable,因此必须手动处理。您目前正在从Image返回GenerateImage,但在保存后不会将其丢弃。