【问题标题】:DrawToBitmap - System.ArgumentException: Parameter is not validDrawToBitmap - System.ArgumentException:参数无效
【发布时间】:2012-08-13 08:15:16
【问题描述】:

我正在创建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 上使用它,一切都会完美运行。即使我不在位图上使用它也很好。两个答案都很好,我只能接受其中一个:(

【问题讨论】:

    标签: c# .net bitmap system.drawing


    【解决方案1】:

    因此,该错误消息来自 GDI+ 的深处,并且可能出于很多 的原因出现。但是,我发现您的代码存在一个明显的问题,即候选代码:

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

    Font 对象实现了IDisposable,你在一个紧密的循环中创建了很多对象,并且从不调用Dispose()。位图本身也是如此。我敢打赌 GDI 的资源已经用完了。

    很难理解您的代码。它基本上什么都不做,只是创建了大量的FontBitmap 对象,所以我什至不能建议将这些声明中的每一个都包含在using 语句中。除此之外,当您连续快速创建大量 GDI 对象而不处置它们时,您最终会遇到这个问题。

    如果您需要这些对象在一段时间内有效,那么您需要确保稍后对它们调用Dispose() 以尽可能及时地释放本机资源(终结器会为您执行此操作,但它是最好不要等到它)。如果它们是本地对象,则将它们包装在 using 语句中,以便在块退出时调用 Dispose()

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

    【讨论】:

    • 嗨。起初我尝试使用(位图...)=>根本没有变化。但是当我在每次通话结束时使用 label.Dispose() 时,一切都很好:) 谢谢 - 用 30.000 次通话对其进行了测试,我认为现在很好。没有 label.Dispose() 我在 1000-2000 次调用后得到异常。从没想过我必须 dispose() 标签。
    • @miri:就像@HansPassant:我原以为处理标签会导致异常。我相信应该将字体和位图包装在using 块中。我不知道您如何能够在不了解标签的其他用途的情况下摆脱标签的处理。
    【解决方案2】:

    GDI+ 异常相当糟糕,它们通常不能很好地描述真正的问题。在这种情况下,它实际上意味着“位图太大”。它仍然不能很好地描述它,你实际上用完了非托管内存。位图太大,无法容纳仍然可用的内存量。

    因为您没有在位图上调用 Dispose() 方法。您通常可以忽略这一点而不会注意到麻烦。但不是 Bitmap,它是一个占用很少垃圾回收内存但占用大量非托管内存的类。它没有足够快地触发垃圾收集器,无法让终结器释放非托管内存。

    代码 sn-p 没有意义,但你可以这样写以避免异常:

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

    【讨论】:

    • 我真的,seriously 讨厌 GDI 错误消息...它需要经验才能诊断问题,这使得消息本身毫无用处。
    • 感谢您的创意! Dispose() 很棒,但不知何故我需要在标签上使用它。
    • 嗯,不,很确定你不想处理标签,这会使它消失并让你的代码崩溃。处理位图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多