Problem: how can I save/compress bitmap images (several of them stacked in tiff
file) asynchronously with respect to the main thread?
My setting: (synchronous & slow working solution: when the compression is performed the thread remains stuck for a few seconds. I cannot afford this.)
...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;
}
}
What I've been trying: I would like the compression (the call encoder.save(fs)
) to be performed in another thread than the main one.
I tried to put the call encoder.save(fs)
in a BackgroundWorker
which preventively copies the encoder to a local version (not sure if it worked though) and then makes the call.
I receive an error like 'The calling thread cannot access this object because a different thread owns it'.
If I use a Dispatcher.Invoke
(provided I do it correctly) the execution becomes again very slow.
Am I make some stupid mistake?
EDIT: (work in progress following the suggestions of @meilke and @user7116)
I now moved the allocation and the execution of the compressor in a BackgroundWorker
. Although now colorBitmap
which is passed, owns to another thread. I tried to freeze
it, but it doesn't look enough; I still get a 'The calling thread cannot access this object because a different thread owns it'.
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)
{
..
}
}
};
I am no computer scientist, but I found this post, which states:
And, it looks to me like you are steping outside of the DispatcherObject's permissions.