C# Threading Bitmap objects/PictureBox
I have some code to display video-like graphics of points moving around.
I am writing the points to a bitmap, and placing it on a picturebox.
The graphics computation has to be done on its own thread. The graphics work fine as long as you don't move the window around "too" much.
I'm using winforms. When I run the code, and move the window around wildly, I SOMETIMES get the following errors:
@ this.Invoke(d, new object[ ] { bmp }); "Cannot access a disposed object. Object name: 'Form1'."
@ gfx.DrawImage(bmpDestination, new Point()); "Object is currently in use elsewhere."
Here is the code:
private void button2_Click(object sender, EventArgs e)
{
Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));
demoThread.Start();
}
private void ThreadProcSafe()
{
creategraphics();
}
private void creategraphics()
{
Bitmap bmpDestination = new Bitmap(988, 588);
Bitmap bmp = new Bitmap(988, 588);
for (int i = 0; i < numtimesteps; i++)
{
bmp = GraphingUtility.create(apple, i, 988, 588, -30, 30, -30, 30);
using (Graphics gfx = Graphics.FromImage(bmp))
{
gfx.DrawImage(bmpDestination, new Point());
}
bmpDestination = bmp;
updateimage(bmp);
}
}
delegate void graphicscallback(Bitmap bmp);
private void updateimage(Bitmap bmp)
{
if (pictureBox1.InvokeRequired)
{
graphicscallback d = new graphicscallbac开发者_StackOverflow社区k(updateimage);
this.Invoke(d, new object[] { bmp });
}
else
{
pictureBox1.Image = bmp;
pictureBox1.Refresh();
}
}
There are problems using GDI objects across threads.
Look at Hans' double-clone suggestions in this thread.
Cannot access a disposed object. Object name: 'Form1
You get this because you don't do anything to stop the thread when the user closes the form. You'll have to keep the form alive until you know that the thread is dead. Pretty hard to do reliable, check this answer for a solution.
As an aside, calling InvokeRequired is an anti-pattern. You know that you are making the call from a worker thread. If InvokeRequired would return false then there's something really wrong. Don't bother, call Invoke() directly.
Object is currently in use elsewhere
It is an exception raised by GDI+ (Graphics) when it sees that two threads are trying to access a bitmap at the same time. It isn't obvious in your snippet but I can't see what GraphingUtility.create() does. Make sure it creates a new bitmap, not return an existing one. Because that will bomb when your thread writes to it again and the picture box repaints itself at the same time. The bmp constructor you use above it doesn't do anything.
Your PictureBox.Image assignment is forgetting to dispose the old one.
精彩评论