Проблема: как я могу сохранять/сжимать растровые изображения (несколько из них сложены в файл tiff
) асинхронно по отношению к основному потоку?
Моя настройка: (синхронное и медленное рабочее решение: когда выполняется сжатие, поток зависает на несколько секунд. Я не могу себе этого позволить.)
...in the body of a window class
private void afunction(){
//called with a given frequency and updating this.colorBitmap
...
this.colorBitmap = something;
savePictureStackTiff();
}
private int stack_pict_count = 0;
private int PICT_PER_FILE = 45;
private TiffBitmapEncoder encoder;
private string savePictureStackTiff()
{
initializeTiffEncoder();
//make a local copy of the image I want to put in the tiff binder
WriteableBitmap localCopy = new WriteableBitmap(this.colorBitmap);
encoder.Frames.Add(BitmapFrame.Create(localCopy));
stack_pict_count++;
if (stack_pict_count % PICT_PER_FILE == 0)
//Once I have enough files stacked I ask for compression
{
stack_pict_count = 0;
pict_metadata = "";
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs); //<<<== LINE WHICH I'D LIKE TO BE RUN ASYNC
}
}
catch (IOException)
{}
}
}
private void initializeTiffEncoder()
{
if (stack_pict_count == 0)
{
encoder = new TiffBitmapEncoder();
encoder.Compression = TiffCompressOption.Zip;
}
}
Что я пробовал: я хотел бы, чтобы сжатие (вызов encoder.save(fs)
) выполнялось в другом потоке, а не в основном.
Я попытался поместить вызов encoder.save(fs)
в BackgroundWorker
, который превентивно копирует кодировщик в локальную версию (хотя не уверен, что это сработало), а затем выполняет вызов. Я получаю сообщение об ошибке, например 'Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку'.
Если я использую Dispatcher.Invoke
(при условии, что я делаю это правильно), выполнение снова становится очень медленным.
Я делаю какую-то глупую ошибку?
EDIT: (работа в процессе, следуя предложениям @meilke и @user7116)
Теперь я переместил выделение и выполнение компрессора в файл BackgroundWorker
. Хотя теперь colorBitmap
, который передается, принадлежит другому потоку. Я пытался freeze
сделать это, но этого недостаточно; Я по-прежнему получаю сообщение "Вызывающий поток не может получить доступ к этому объекту, поскольку им владеет другой поток".
tiffCompressorWorker = new BackgroundWorker();
tiffCompressorWorker.DoWork += (s, a) =>
{
initializeTiffEncoder();
WriteableBitmap localCopy = new WriteableBitmap((WriteableBitmap)a.Argument);
localCopy.Freeze();
encoder.Frames.Add(BitmapFrame.Create(localCopy));
stack_pict_count++;
if (stack_pict_count % PICT_PER_FILE == 0)
{
stack_pict_count = 0;
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
saving_encoder.Save(fs);
}
}
catch (IOException)
{
..
}
}
};