位图.保存"对象目前正在其他地方使用"线程问题

本文关键字:quot 方使用 线程 问题 其他 目前 保存 对象 位图 | 更新日期: 2023-09-27 18:13:50

我有一些这样的代码:

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

我有一个for循环使用下面类似的代码创建x数量的图像:

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);
}

我认为通过把SaveImage方法作为一个任务,这将加快速度,但我认为我得到的异常是因为循环的下一次迭代是试图绘制到最终的图像对象,而保存正在发生。我想我可以用一把锁,但我担心那样会减慢速度。

是否有一个修复或我应该只是删除任务?

位图.保存"对象目前正在其他地方使用"线程问题

实际上,您不能同时从多个线程访问图像。你需要做一些同步。如果性能是一个问题,您可以执行以下技巧:

在您的保存方法中,对图像进行锁定。保存到内存流,释放锁,最后保存到磁盘。(因为磁盘IO非常慢)。

锁部分只有在需要实际同步时才有用。由于Bitmap不是线程安全的,因此首先不应该使用多个线程访问它,因此同步应该不是问题。

绘制位图并将其保存在另一个线程中是完全可以的,只要您不同时这样做。GDI+包含一个检查来验证你不会在同一时间从多个线程访问位图,这就是为什么你得到异常。

一个简单的解决方法是在开始绘制之前创建一个新的位图。保存后将其处理在任务中。你必须仔细编写代码,如果保存位图的时间比绘制时间长,你仍然会遇到问题。您将耗尽内存。信号量可以解决这个问题,将它初始化为你满意的位图数。取决于位图的大小。然后在绘图方法中调用WaitOne(),在保存方法中调用Release()。