我正在使用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线程中创建的,但是如何 我可以解决它吗?
非常感谢帮助! :)
答案 0 :(得分:5)
在调用Dispatcher.Invoke
之前调用BitmapSource.FreezeBitmapSource _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线程,然后下载的东西......我一直在犯这个错误我的几个项目,并想知道为什么用户界面没有回应......