C# Threading Lock error when merging images

c#, locking, multithreading

Solution

The error is occurring because your UI thread is using the image (in particular, setting the pictureBox.Image = someImage will cause the .NET framework's ImageAnimator class to look at the image, seeing if it should animate it (for animated .GIF images, for example).

Meanwhile, your background thread is changing the image, thus causing the WinForms code to throw a "Object is currently in use elsewhere" exception.

The following code works for me, never crashes no matter how many threads I throw at it:

lock (locker)
{
  using (Graphics gr = Graphics.FromImage(bmp2))
  {
      gr.DrawImage(Resources.someImage, new Rectangle(0, 0, 800, 600));
      pictureBox1.Invoke(new Action(() => pictureBox1.Image = bmp2));
  }
}

Shoot, turns out that didn't work, either. Throw enough threads at that, and it will crash.

I suspect the problem is related to Win32 painting your bitmap while the background thread is drawing on it. One (UI) thread reading, one (background) thread writing. That's bound to lead to issues.

The best fix for multi-threading bugs like this is often to stop sharing data between threads. Instead, duplicate the data, and let each thread have its own local copy. Here's an example:

lock (locker)
{
    using (Graphics gr = Graphics.FromImage(bmp2))
    {
        gr.DrawImage(Resources.someImage, new Rectangle(0, 0, 800, 600));
        var clone = bmp2.Clone() as Image;
        pictureBox1.Invoke(new Action(() => pictureBox1.Image = clone));
    }
}

Problem

I'm trying to make a multithreaded program that takes a certain bitmap from a picturebox where each thread analyzes and changes part of it and then saves it back to the picturebox. I've used a lock() for the instructions that deal with the shared bitmap object and the picturebox but for some reason i still get "Object is currently in use elsewhere" errors every 6-10 runs. ``` private Object locker = new Object(); void doThread(Bitmap bmp2) //simplified - other references not important { //some code here //.... lock (locker) { Graphics gr = Graphics.FromImage(bmp2); //this is where i get the errors, they're related to bmp2 gr.DrawImage(bmp, new Rectangle(0, 0, 800, 600)); gr.Dispose(); pictureBox1.Image = bmp2; } } void runThreads() { Bitmap bmp2 = new Bitmap(pictureBox1.Image); Thread thread1 = new Thread(delegate() { doThread(bmp2); }); Thread thread2 = new Thread(delegate() { doThread(bmp2); }); Thread thread3 = new Thread(delegate() { doThread(bmp2); }); Thread thread4 = new Thread(delegate() { doThread(bmp2); }); thread1.Start(); thread2.Start(); thread3.Start(); thread4.Start(); } ``` I've tried to read as much as I could find on the lock() method but it's still a bit unclear so I might have misused it. So my question is, why isn't the lock preventing threads from executing the instructions? Have I misused it? Or is there a workaround I could use? Any help with this is greatly appreciated.

Original source