通用GDI +错误:调用GC.Collect()时避免

时间:2011-04-14 22:40:02

标签: c# garbage-collection

我有这段代码(“ruta1”和“ruta2”是包含不同图像路径的字符串):

   Bitmap pic;
   Bitmap b = new Bitmap(SomeWidth, SomeHeight);
   g = Graphics.FromImage(b);
   g.FillRectangle(new SolidBrush(Color.White), 0, 0, b.Width, b.Height);

   b.Save(ruta2, ImageFormat.Jpeg);
   g.Dispose();
   b.Dispose();

   b = new Bitmap(OtherWidth, OtherHeight);
   pic = new Bitmap(ruta2);
   g = Graphics.FromImage(b);
   g.FillRectangle(new SolidBrush(Color.White), 0, 0, b.Width, b.Height);
   g.DrawImage(pic, 0, 0, pic.Height, pic.Width); 

   pic.Dispose();
   b.Save(ruta2, ImageFormat.Jpeg);
   g.Dispose();
   b.Dispose();

   pic = new Bitmap(ruta1);
   b = new Bitmap(AnotherWidth, AnotherHeight);
   g = Graphics.FromImage(b);
   g.FillRectangle(new SolidBrush(Color.White), 0, 0, b.Width, b.Height);

   int k = 1;

   // I just draw the "pic" in a pattern on "b"
   for (h = 0; h <= b.Height; h += pic.Height)
       for (w = 0; w <= b.Width; w += pic.Width)
            g.DrawImage(pic, w, h, k * pic.Width, k * pic.Height);

   pic.Dispose();            
   GC.Collect();  // If I comment this line, I get a "generic GDI+ Error" Exception
   b.Save(ruta1, ImageFormat.Jpeg);
   g.Dispose();
   b.Dispose();

如果我在处理后设置pic = null并不重要,如果我不调用垃圾收集器,我会得到“通用GDI +错误”异常。只有当我打电话给垃圾收集器时,我的程序才会一直运行。

有人可以解释这种行为吗?它取决于.Net框架版本吗? 我正在使用Visual C#Express 2008,带有.Net framework 3.5

1 个答案:

答案 0 :(得分:1)

首先,如果您使用“using”关键字来限制使用一次性对象(例如BitmapGraphics),而不是调用{{{ 1}}每个人手动。使用“Dispose()”更好的原因有很多,例如在抛出异常时清理东西,但它也极大地有助于代码的可读性。

其次,GDI画笔也是using个对象,所以你不应该创建 - 忘记它们。这样做:

IDisposable

...或者更好的是,在应用程序开始时创建您的画笔,并持续到它们直到结束(但不要忘记也将它们丢弃)。 IIRC,如果频繁地进行,创建/处理刷子会对性能产生很大的影响。

第三,我相信你的错误在第二部分:

  1. 您打开图片“ruta2”
  2. 您创建新图片
  3. 您在新图片中绘制“ruta2”的内容
  4. 你将这个新东西保存在“ruta2”文件的顶部,但是第1步中的原始图像仍然被加载,并且可能对“ruta2”文件有一些处理,所以你需要在覆盖之前处理它文件。
  5. 如果您像这样重构第二部分,它应该有效:

    using (var brush = new SolidBrush(Color.White))
    {
        g.FillRectangle(brush, 0, 0, width, height)
    }