WPF/BackgroundWorker和BitmapSource问题

问题描述:

我是WPF的初学者,正在尝试一个家庭项目以熟悉该技术.我有一个简单的表单,用户可以选择一个图像文件,然后显示EXIF数据以及该图像的缩略图.这可以正常工作,但是当我选择一个RAW图像文件(〜9 MB)时,拇指加载时会稍有延迟,因此我想我可以使用BackgroundWorker对该图像进行解码,并且用户可以查看EXIF数据,然后图像解码后显示.

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.

BitmapSource对象在BackgroundWorkers DoWork方法中声明:

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

我遇到的问题是,当我尝试在RunWorkerCompleted方法中设置Image控件的源时,我收到一个错误,因为该对象归另一个线程所有.

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

我尝试使用imgThumb.Dispatcher.BeginInvoke()方法设置源,但这也不起作用,我想这是因为args.Result是另一个线程拥有的,而不是imgThumb?我该如何解决?

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?

可能是我的Dispatcher编码错误(以下是从内存中删除的,我删除了已有的东西).

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

欢迎任何建议或想法.

更新

将我的DoWork方法更改为使用BitmapCreateOptions.None而不是.DelayCreation,但是现在在加载RAW文件时出现以下错误(Canon .CR2文件是我迄今为止测试过的全部文件),该代码适用于jpg.我安装的允许我显示RAW文件的佳能编解码器是否会出现问题?

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?

该应用程序称为接口 被编组为不同的 线. (来自HRESULT的异常: 0x8001010E(RPC_E_WRONG_THREAD))

The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

在BitmapSource上调用Freeze(),您将不会遇到此问题(冻结摆脱了线程限制,但使对象不可变)

Call Freeze() on the BitmapSource and you won't have this problem (Freezing gets rid of the threading restrictions, but makes the object immutable)