通用GDI+错误:在调用GC.Collect()时避免
本文关键字:Collect GC 错误 GDI+ 调用 通用 | 更新日期: 2023-09-27 17:50:10
我有这段代码("ruta1"answers"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框架3.5首先,如果您使用" using
"关键字来限定一次性对象(如Bitmap
和Graphics
)的使用范围,而不是对每个对象手动调用Dispose()
,那就更好了。使用"using
"有很多更好的原因,比如在抛出异常时清理东西,但它也极大地有助于代码的可读性。
第二,GDI笔刷也是IDisposable
对象,所以你不应该创建并忘记它们。这样做:
using (var brush = new SolidBrush(Color.White))
{
g.FillRectangle(brush, 0, 0, width, height)
}
…或者更好的是,在应用程序开始时创建画笔,并一直使用到最后(但也不要忘记处理它们)。IIRC,如果频繁创建/处理画笔,会对性能产生很大影响。
第三,我相信你的bug在第二部分:
- 打开图片"ruta2"
- 创建新图像
- 在新图像中绘制ruta2的内容
- 你把新东西保存在"ruta2"文件的顶部,但是从第一步开始的原始图像仍然被加载,并且可能对"ruta2"文件有一些处理,所以你需要在覆盖文件之前处理它。
如果你像这样重构第二部分,它应该可以工作:
using (var b = new Bitmap(OtherWidth, OtherHeight))
using (var g = Graphics.FromImage(b))
{
using (var brush = new SolidBrush(Color.Red))
{
g.FillRectangle(brush, 0, 0, b.Width, b.Height);
}
using (var pic = new Bitmap(ruta2))
{
g.DrawImage(pic, 0, 0, pic.Height, pic.Width);
}
b.Save(ruta2, ImageFormat.Jpeg);
}