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 :(
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
GDI+ exceptions are fairly poor, they often don't describe the real issue well. In this case it really means "the bitmap is too large". Which still doesn't it describe it well, you are actually running out of unmanaged memory. The bitmap is too large to fit the amount of memory still available.
Because you are not calling the Dispose() method on the bitmap. You can often skimp on that without noticing trouble. But not with Bitmap, it is a class that takes very little garbage collected memory but a lot of unmanaged memory. It doesn't trigger the garbage collector quick enough to let the finalizer release the unmanaged memory.
The code snippet doesn't make sense, but you'd write it like this to avoid the exception:
using (Bitmap image = new Bitmap(300, 500)) {
label.DrawToBitmap(image, label.ClientRectangle);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With