0

我正在使用 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 线程中返回错误。我知道它是因为当它是在 BackgroundWorker 线程中创建时,我从调度程序 GUI 线程访问它,但我该如何解决呢?

帮助将不胜感激!:)

4

4 回答 4

5

只需在调用 Dispatcher.Invoke 之前调用 BitmapSource.Freeze

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

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

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

于 2009-08-04T10:46:13.230 回答
0

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

Dispatcher.Invoke(DispatcherPriority.Background,
    new Action(() => { CaptchaBitmap = GetCaptchaFromServer(); } )
);
于 2009-08-04T09:51:56.053 回答
0

我遇到了同样的问题WPF:在 UI 线程和后台线程之间传递对象 还没有弄清楚什么是“正确”的解决方案。最终将我的 BackgroundWorker 替换为仅运行一次且有效的 DispatcherTimer。

于 2009-08-04T09:41:57.120 回答
0

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

于 2009-08-05T11:52:03.457 回答