I had made an app in C# that will perform screen capture continuously and display it in a PictureBox using timer. After running for a few seconds, there was an ArgumentException.
Below is the code and the line that has the ArgumentException
private void timer1_Tick(object sender, EventArgs e)
{
Rectangle bounds = Screen.GetBounds(Point.Empty);
Graphics graphics;
Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
using (graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(0, 0, 0, 0, new Size(bounds.Width , bounds.Height )); // ArgumentException
pictureBox1.Image = bitmap;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
}
Besides that, I had notices that an alert saying low memory from Windows after running the app for a few seconds.
Any tips on resolving this problem?
Yes, your program won't last long when you frequently update the picture box. The Bitmap class is the singular .NET class where IDisposable can't easily be ignored. It is like an iceberg, bitmaps can use massive amounts of unmanaged memory but very little managed memory. You must dispose bitmaps when you no longer use them to prevent them from consuming all available unmanaged memory for their pixel data. The garbage collector tends to hide that problem but it can't do so when it doesn't run frequently enough. And the managed portion of Bitmap is too small to trigger a collection often enough. Fix:
You keep setting a new bitmap to the picturebox, and the previous bitmap is never disposed. After a while, the system runs short of GDI handles and/or memory (running your code, I consumed one gig of memory in under 15 seconds).
You can simply reuse your existing bitmap:
You also don't have to reset
pictureBox1.SizeMode
on each iteration.Alternatively, you can dispose the previous bitmap manually:
The following KB can help understanding this issue: Bitmap and Image constructor dependencies
One has to figure out when is the object ready for disposal.