2012-08-16 97 views
5

Im创建Label,有时使用.DrawToBitmap()。我不知道为什么,但是我运行后我计划了一段时间(和调用.DrawToBitmap()经常)我得到异常:DrawToBitmap - System.ArgumentException:参数无效

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上使用它,一切都很完美。即使我不使用它在位图上的罚款。这两个答案都很好,我只能接受其中一个:(我的

回答

6

所以,这个错误信息来自GDI +内部的深处,可能会出现很多的原因。我看到一个明显的代码问题即然候选人:。

label.Font = new Font("Arial", 20); 

Font对象实现IDisposable和你在一个紧密的循环创造了他们很多,从来没有叫Dispose()也是一样的位图本身我敢打赌,GDI用完的资源

它是har d来理解你的代码。它基本上完全没有什么,但创建了大量的FontBitmap对象,所以我甚至不能建议将这些声明中的每一个都包含在using声明中。除此之外,当你连续创建大量GDI对象而不处理它们时,你最终会遇到这个问题。

如果您需要这些对象有效一段时间,那么您需要确保您稍后调用Dispose()以尽可能及时地释放本地资源(终结器将为您做到这一点,但它是最好的不要等待它)。如果它们是本地对象,然后将它们包装在using语句,以便将Dispose()块时退出被称为:

using(var b = new Bitmap(w, h)) 
{ 
    // use 'b' for whatever 
} // b.Dispose() is called for you 
+0

嗨。起初,我尝试使用(位图...)=>没有任何改变。但是当我在每次调用结束时使用label.Dispose()时,一切都很好:)谢谢 - 用30.000次调用测试它,现在我认为这很好。没有label.Dispose()我在1000-2000次调用后得到异常。从来没有想过我必须处置()标签。 – miri 2012-08-16 22:48:01

+0

@miri:就像@HansPassant:我以为处置标签会导致异常。我相信这是应该用'使用'块包装的字体和位图。我不知道如何在不看标签的情况下处理标签。 – IAbstract 2012-08-17 14:11:12

4

GDI +的例外是比较差的,他们往往没有说明真正的问题很好。在这种情况下,它确实意味着“位图太大”。它仍然不能很好地描述它,你实际上已经用完了非托管内存。位图太大而不适合仍可用的内存量。

因为您没有在位图上调用Dispose()方法。你可以经常吝啬,而不会注意到麻烦。但与位图不同,这是一个只需要很少的垃圾收集内存,但有很多非托管内存的类。它不会足够快地触发垃圾收集器,让终结器释放非托管内存。

的代码片断是没有意义的,但你会写这样避免了异常:

using (Bitmap image = new Bitmap(300, 500)) { 
    label.DrawToBitmap(image, label.ClientRectangle); 
} 
+1

我认真对待*严重*讨厌GDI错误信息......它只需要经验来诊断问题,这使得信息本身无用。 – 2012-08-16 22:40:20

+0

谢谢你的想法! Dispose()很好,但不知何故,我需要在标签上使用它。 – miri 2012-08-16 22:48:54

+0

嗯,不,很确定你不想处理这个标签,那会让它消失并且使你的代码崩溃。配置位图。 – 2012-08-16 23:36:59