I am a beginner with WPF and trying a home project to become familiar with the technology. I have a simple form where the user selects an image file, I then display EXIF data along with a thumbnail of the image. This is working fine but when I select a RAW image file (~9 MB) there can be a slight delay while the thumb loads, so I thought I could use the BackgroundWorker to decode the image and the user can view the EXIF data, then when the image has been decoded it is displayed.
The BitmapSource object is declared in the BackgroundWorkers DoWork method:
worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
string filePath = args.Argument as string;
BitmapDecoder bmpDecoder = BitmapDecoder.Create(new Uri(filePath), BitmapCreateOptions.None, BitmapCacheOption.None);
BitmapSource bmpSource = bmpDecoder.Frames[0];
bmpSource.Freeze(); //As suggested by Paul Betts
args.Result = bmpSource;
};
the problem that I'm running into is when I try to set the source of my Image control in the RunWorkerCompleted method I receive an error because the object is owned by another thread.
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
imgThumb.Source = args.Result as BitmapSource;
};
I tried using the imgThumb.Dispatcher.BeginInvoke()
method to set the source but this didn't work either, I guess it's because it's the args.Result
that is owned by another thread, and not the imgThumb
? How can I get round this?
It could be that I was coding my Dispatcher wrong (the following is from memory, I deleted what I had).
imgThumb.Dispatcher.Invoke(new Action<BitmapSource>(
delegate(BitmapSource src)
{
imgThumb.Source = src;
}
), bmpSource);
Any suggestions or ideas are welcome.
Update
Changed my DoWork method to use BitmapCreateOptions.None rather than .DelayCreation but now I get the following error when loading RAW files (Canon .CR2 files is all I have tested to date), the code works fine for jpg's. Could this be an issue with the Canon Codec I installed to allow me to display the RAW files?
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
Call Freeze() on the BitmapSource and you won't have this problem (Freezing gets rid of the threading restrictions, but makes the object immutable)
I had exactly the sample problem and was lucky to solve it.
Short answer: wrap in WriteableBitmap
. That comes at a little price, thou.
来源:https://stackoverflow.com/questions/2128438/wpf-backgroundworker-and-bitmapsource-problem