Bitmap.Save «Объект используется в другом месте» - PullRequest
3 голосов
/ 09 ноября 2011

У меня есть такой код:

    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 в качестве задачи, это ускорит процесс, но я предполагаю, что получаю исключение, потому что следующая итерация цикла пытается нарисовать конечный объект изображения, пока происходит сохранение. Я думаю, я мог бы использовать замок, но я боюсь, что это может замедлить ход событий?

Есть ли исправление или я должен просто удалить задачу?

Ответы [ 2 ]

3 голосов
/ 09 ноября 2011

Действительно, вы не можете получить доступ к изображению из нескольких потоков одновременно.Вы должны сделать некоторую синхронизацию.если производительность является проблемой, вы можете выполнить следующий трюк:

В вашем методе сохранения получите блокировку изображения.Сохраните в поток памяти, снимите блокировку и, наконец, сохраните на диск.(поскольку дисковый ввод-вывод очень медленный).

Часть блокировки полезна только при необходимости фактической синхронизации.Поскольку растровое изображение не является поточно-ориентированным, вы не должны получать к нему доступ, используя в первую очередь несколько потоков, и, следовательно, синхронизация не должна быть проблемой.

2 голосов
/ 09 ноября 2011

Рисовать в растровое изображение и сохранять его в другом потоке - это прекрасно, если вы не делаете это одновременно.GDI + содержит проверку, чтобы убедиться, что вы не обращаетесь к растровому изображению более чем из одного потока одновременно, поэтому вы получаете исключение.

Простой обходной путь - создать new растровое изображение, прежде чем начать рисовать.Удалите его в задании после того, как вы его сохранили.Вы должны тщательно это кодировать, у вас все равно будет проблема, если сохранение растрового изображения займет больше времени, чем рисование.Вам не хватит памяти.Семафор может решить эту проблему, инициализируя его тем количеством растровых изображений, с которым вам удобно.Зависит от размера растрового изображения.Затем вызовите WaitOne () в методе рисования, Release () в методе сохранения.

...