我正在创建Label
,有时使用.DrawToBitmap()
创建。我不知道为什么,但在我运行我的程序一段时间后(经常调用.DrawToBitmap()
)我得到了例外:
System.ArgumentException: Parameter is not valid.
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, PixelFormat format)
at System.Drawing.Bitmap..ctor(Int32 width, Int32 height)
不知怎的,我不能经常调用这个函数。如果我从根本上尝试这个:
while(true)
{
System.Windows.Forms.Label label = new Label();
label.Font = new Font("Arial", 20);
label.Text = "test";
try
{
Bitmap image = new Bitmap(300, 500);
label.DrawToBitmap(image, label.ClientRectangle);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
我在5-6秒(1000-2000次通话)之后得到了例外。问题是什么?怎么避免这个?
编辑:谢谢大家Dispose()
的想法 - 如果我在label
上使用它,那么一切都很完美。即使我不在Bitmap上使用它也没关系。这两个答案都很棒,我只能接受其中的一个:(
答案 0 :(得分:6)
因此,该错误消息来自GDI +的内心深处,并且可能出现很多的原因。我看到你的代码有一个明显的问题,但是:
label.Font = new Font("Arial", 20);
Font
个对象实现了IDisposable
,你在紧密的循环中创建了很多对象,从不调用Dispose()
。 Bitmap本身也是如此。我敢打赌,GDI资源不足。
很难理解你的代码。除了创建大量的Font
和Bitmap
对象之外,它基本上什么都不做,所以我甚至不建议在using
语句中包含每个声明。除此之外,当你快速连续创建大量GDI对象而不处理它们时,你最终会遇到这个问题。
如果您需要这些对象有效一段时间,那么您需要确保稍后调用它们Dispose()
以尽可能及时地释放本地资源(终结器将为您执行此操作,但最好不要等到它。如果它们是本地对象,则将它们包装在using
语句中,以便在块退出时调用Dispose()
:
using(var b = new Bitmap(w, h))
{
// use 'b' for whatever
} // b.Dispose() is called for you
答案 1 :(得分:4)
GDI +异常相当差,他们通常不能很好地描述真正的问题。在这种情况下,它实际上意味着“位图太大”。它仍然不能很好地描述它,你实际上已经耗尽了非托管内存。位图太大,无法容纳仍然可用的内存量。
因为您没有在位图上调用Dispose()方法。你可以经常在不注意麻烦的情况下吝啬。但是不是Bitmap,它是一个类,它只需要很少的垃圾收集内存,但需要很多非托管内存。它不会足够快地触发垃圾收集器,让终结器释放非托管内存。
代码片段没有意义,但您可以这样写它以避免异常:
using (Bitmap image = new Bitmap(300, 500)) {
label.DrawToBitmap(image, label.ClientRectangle);
}