WPF/BackgroundWorker和BitmapSource问题

5
我是一个初学者,正在尝试使用WPF技术进行家庭项目以熟悉该技术。我有一个简单的表单,用户选择图像文件,然后我会显示EXIF数据以及图像的缩略图。这很好用,但是当我选择一个RAW图像文件(约9 MB)时,加载缩略图可能会有轻微的延迟,因此我认为我可以使用BackgroundWorker来解码图像,用户可以查看EXIF数据,然后当图像被解码时它会被显示。
BitmapSource对象在BackgroundWorker的DoWork方法中声明:
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控件的源时,由于该对象归另一个线程所有,因此会收到错误提示。
worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
{
    imgThumb.Source = args.Result as BitmapSource;
};

我尝试使用imgThumb.Dispatcher.BeginInvoke()方法设置源,但这也没有起作用,我想这是因为args.Result归另一个线程所有,而不是imgThumb。如何解决这个问题?可能是我在编写Dispatcher时出错了(以下内容是从记忆中删除的)。
imgThumb.Dispatcher.Invoke(new Action<BitmapSource>(
    delegate(BitmapSource src)
    {
        imgThumb.Source = src;
    }
), bmpSource);

任何建议或想法都受欢迎。
更新
将我的DoWork方法更改为使用BitmapCreateOptions.None而不是.DelayCreation,但现在在加载RAW文件(我只测试过Canon .CR2文件)时出现以下错误,对于jpg文件,代码运行良好。这可能是我安装的用于显示RAW文件的佳能解码器的问题吗?
引用:
应用程序调用了一个为不同线程编组的接口。(HRESULT异常:0x8001010E(RPC_E_WRONG_THREAD))
2个回答

8
在BitmapSource上调用Freeze(),您就不会遇到这个问题(冻结会消除线程限制,但会使对象不可变)。

我在DoWork方法中设置BitmapSource值后添加了Freeze()调用。然后我在RunWorkerCompleted方法中添加了以下行:BitmapSource xx = args.Result; 这给了我与之前相同的错误。我是否遗漏了任何明显的东西?我已经删除了使用Dispatcher的任何代码。 - Fermin
我之前很蠢,但现在遇到了不同的错误,已经更新了问题。 - Fermin
即使过了许多年,非常感谢。一直在网上寻找这个。 - Kulpemovitz

2

我曾经遇到过完全相同的问题,很幸运地解决了它。

简短回答:用WriteableBitmap包装一下。但是这样做会有一点代价。

详细回答


对于我的情况,这是唯一有效的解决方案。我需要将一个BitmapFrame输入到TransformedBitmap中。由于它是由库提供的(并且BitmapFrame的Dispatcher属性为null),因此无法控制BitmapFrame创建的线程。即使查询CanFreeze属性也会导致异常。我有两个选择:彻底重构我的和其他人的源代码,或者使用WriteableBitmap。猜猜我选择了哪一个... - user2819245

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接