如何访问Dispatcher中的WPF对象?

时间:2009-08-04 09:14:34

标签: wpf multithreading mvvm backgroundworker

我正在使用MVVM模式开发WPF应用程序。

应用程序从服务器加载验证码图像并分配它 准备好后,在WPF表单上的图像。我正在使用 BackgroundWorker为我做线程,如下:

加载Window时,会调用以下内容:

BackgroundWorker _bgWorker = new BackgroundWorker();

_bgWorker.DoWork += GetCaptchaImage;
_bgWorker.RunWorkerAsync();

GetCaptchaImage函数非常简单,加载图像 在另一个主题中:

BitmapSource _tempBitmap = GetCaptchaFromServer();

我需要知道如何调用Dispatcher来分配它 ImageSource到我的Window的图像源,目前我调用了 加载_tempBitmap后的调度程序如下:

Application.Current.Dispatcher.Invoke(
new Action(() => CaptchaBitmap = _tempBitmap));

将CaptchaBitmap数据绑定到我的图像源。

但是,当我这样做时,会抛出InvalidOperationException, 并且对_tempBitmap的任何引用都会在GUI中返回错误 线。我知道它,因为我从调度员那里访问它 GUI线程,它是在BackgroundWorker线程中创建的,但是如何 我可以解决它吗?

非常感谢帮助! :)

4 个答案:

答案 0 :(得分:5)

在调用Dispatcher.Invoke

之前调用BitmapSource.Freeze
BitmapSource _tempBitmap = GetCaptchaFromServer();
_tempBitmap.Freeze();
Application.Current.Dispatcher.Invoke(
new Action(() => CaptchaBitmap = _tempBitmap));

所有WPF对象只能从创建它们的线程访问,例外是Dispatcher(出于显而易见的原因)和Freezable,在你调用冻结方法之后。

在调用Freeze之后,可以从任何线程访问对象(但不能修改),幸运的是BitmapSource继承自Freezable。

答案 1 :(得分:0)

我遇到了同样的问题WPF: Passing objects between UI Thread and Background thread 还没弄清楚什么是“正确的”解决方案。结束使用DispatcherTimer替换我的BackgroundWorker,DispatcherTimer只运行一次并且运行正常。

答案 2 :(得分:0)

出于好奇..为什么不在Dispatcher线程而不是BackgroundWorker类中进行所有检索和设置图像?

Dispatcher.Invoke(DispatcherPriority.Background,
    new Action(() => { CaptchaBitmap = GetCaptchaFromServer(); } )
);

答案 3 :(得分:0)

@Arcturus, 根据我的经验,如果你这样做,你将不会获得任何UI响应,直到从服务器下载完成...因为你实际上是在插入UI线程,然后下载的东西......我一直在犯这个错误我的几个项目,并想知道为什么用户界面没有回应......