如何访问调度程序中的 WPF 对象?

发布于 2024-07-29 12:41:14 字数 858 浏览 4 评论 0原文

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

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

当加载窗口时,调用以下内容:

BackgroundWorker _bgWorker = new BackgroundWorker();

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

GetCaptchaImage 函数相当简单,加载图像 在另一个线程中:

BitmapSource _tempBitmap = GetCaptchaFromServer();

我需要知道如何调用调度程序来分配它 ImageSource 到我的窗口的图像源,目前我称之为 加载 _tempBitmap 后的调度程序如下:

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

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

但是,当我这样做时,会引发 InvalidOperationException, 并且对 _tempBitmap 的任何引用都会在 GUI 中返回错误 线。 我知道它是因为我正在从调度程序访问它 GUI线程,当它是在BackgroundWorker线程中创建的,但是如何 我能绕过它吗?

帮助将不胜感激! :)

I am using the MVVM pattern to develop a WPF application.

The app loads a captcha image from the server, and assigns it
to an Image on the WPF form when ready. I am using a
BackgroundWorker to do the threading for me, as follows:

When the Window is being loaded, the following is called:

BackgroundWorker _bgWorker = new BackgroundWorker();

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

The GetCaptchaImage function is fairly simply, loading an image
in another thread:

BitmapSource _tempBitmap = GetCaptchaFromServer();

I need to know how to Invoke the Dispatcher to assign this
ImageSource to my Window's image source, Currently I call the
dispatcher after loading the _tempBitmap as follows:

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

Where CaptchaBitmap is databound to my image source.

However, when I do this, an InvalidOperationException is thrown,
and any reference to _tempBitmap returns an error in the GUI
thread. I know its because I am accessing it from the dispatcher
GUI thread, when it was created in a BackgroundWorker thread, but how
do I get around it?

Help would be greatly appreciated! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

本宫微胖 2024-08-05 12:41:14

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

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

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

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

Just call BitmapSource.Freeze before calling Dispatcher.Invoke

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

All WPF objects can only be accessed from the thread that created them, the exceptions are Dispatcher (for obvious reasons) and Freezable after you call teh Freeze method.

After calling Freeze the object can be accessed from any thread (but can't be modified), luckily for you BitmapSource inherits from Freezable.

瘫痪情歌 2024-08-05 12:41:14

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

I had the same problem WPF: Passing objects between UI Thread and Background thread
Haven't figured out what "correct" solution is. Ended up replacing my BackgroundWorker with a DispatcherTimer that would run just once and that worked.

傻比既视感 2024-08-05 12:41:14

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

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

Just out of curiousity.. Why don't you do all the retrieving and setting the image in the Dispatcher thread instead of the BackgroundWorker class?

Dispatcher.Invoke(DispatcherPriority.Background,
    new Action(() => { CaptchaBitmap = GetCaptchaFromServer(); } )
);
云朵有点甜 2024-08-05 12:41:14

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

@Arcturus,
From my experience if you do that you won't get any UI responsiveness till the download from the server is complete...because you are actually interupting the UI thread and THEN downloading the stuff...i've been making this mistake in a couple of my projs and wondering why the UI doesn't respond....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文