Bitmap.Save “Object is currently in use elsewhere” Threading Issue

前提是你 提交于 2019-12-10 20:46:34

问题


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?


回答1:


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.




回答2:


Drawing into a bitmap and saving it in another thread is perfectly fine, as long as you don't do it at the same time. GDI+ contains a check to verify that you don't access the bitmap from more than one thread at the same time, that's why you get the exception.

A simple workaround is to create a new bitmap before you start drawing. Dispose it in the task after you saved it. You have to code this carefully though, you'll still have a problem if saving the bitmap takes longer than the drawing. You'll run out of memory. A semaphore can solve that, initialize it to the number of bitmaps you're comfortable with. Depends on the size of the bitmap. Then call WaitOne() in the drawing method, Release() in the saving method.



来源:https://stackoverflow.com/questions/8063404/bitmap-save-object-is-currently-in-use-elsewhere-threading-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!