DrawToBitmap - System.ArgumentException: Parameter is not valid

miri picture miri · Aug 17, 2012 · Viewed 10.9k times · Source

Im creating a Label and sometimes Im using .DrawToBitmap(). I dont know why, but after Im running my program for a while (and calling .DrawToBitmap() often) I get the exception:

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)

Somehow I cannot call this function that often. If I would radically try this:

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);
  }
}

I got after 5-6 secs (1000-2000 calls) the exception. What is the problem? How to avoid this?

Edit: Thank you guys for the idea with Dispose() - somehow everything is working perfect if I use it on label. Even if I dont use it on Bitmap its fine. Both of the answers are great, I can only accept 1 of them :(

Answer

Ed S. picture Ed S. · Aug 17, 2012

So, that error message comes from deep down in GDI+ and may appear for a lot of reasons. I see one glaring problem with your code that is a candidate however:

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

Font objects implement IDisposable and you are creating a lot of them in a tight loop and never calling Dispose(). Same goes for the Bitmap itself. I would bet that GDI is running out of resources.

It's hard to make sense of your code as it stands. It essentially does absolutely nothing but create a ton of Font and Bitmap objects, so I can't even suggest to wrap each of those declarations in a using statement. That aside, when you create a ton of GDI objects in quick succession without disposing of them you will eventually run into this problem.

If you need these objects to be valid for some time then you need to make sure you call Dispose() on them later to release native resources in as timely a manner as possible (the finalizer will do this for you, but it's best not to wait for it to). If they are local objects then wrap them in a using statement so Dispose() will be called when the block exits:

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