Search code examples
c#.netgdi+gdisystem.drawing

Bitmap.Save "Object is currently in use elsewhere" Threading Issue


I have some code like this:

    public void SaveImage(int Counter)
    {
        var task = Task.Factory.StartNew(() =>
        {
            var image = FinalImage;
            if (image != null)
            {
                image.Save(FinalImageSaveLocation + "test" + Counter + ".bmp");
            }
        }, TaskCreationOptions.PreferFairness);
    }

I have a for loop creating x amount of images using similar code below:

for(int i = 0; i < 100; i++)
{
  Pencil.DrawImage(image, x, y); //Pencil is created at a initialisation stage
  SaveImage(i);                  //by Pencil = Graphics.FromImage(FinalImage);
}

I thought by putting the SaveImage method as a task this would speed things up but I assume I'm getting the exception is because the next iteration of the loop is trying to draw to the final image object whilst the Save is occurring. I guess I could use a lock but I fear that would slow things down?

Is there a fix or should I just remove the task?


Solution

  • Indeed, you can't access an image from multiple threads simultaniously. You have to do some synchronization. if performance is a problem, you can perform the following trick:

    In your save method, get a lock on the image. Save to a memory stream, release the lock and finally save to the disk. (since disk IO is very slow).

    The lock part is only usefull when needing actual synchronization. Since a Bitmap is not thread safe, you should not access it using multiple threads in the first place and hence, therefore synchronization shouldn't be a problem.