WPF 调用在长方法处理期间不起作用
在第二个方法 (DoWork) 退出之前,以下方法不会应用 wpf 更改(背景 = 红色):
private void change()
{
Background = Brushes.Red;
Dispatcher.BeginInvoke((Action) DoWork);
}
DoWork() 需要几秒钟才能运行,我真的不想将其放入线程中,因为此代码将是在多个地方使用,并且可能会以不同的时间间隔与 Dispatcher 线程进行交互。我尝试调用 Invalidate...() 方法,但无济于事。添加 BeginInvoke() 是为了查看延迟是否允许在调用逻辑之前应用后台更改。通常,逻辑是该方法的一部分。顺便说一句,大部分逻辑是在不同的线程上执行的,不应该阻塞调度程序线程?!
有人可以帮忙吗? 谢谢
The following method does not apply the wpf changes (background = red) until the 2nd method (DoWork) exits:
private void change()
{
Background = Brushes.Red;
Dispatcher.BeginInvoke((Action) DoWork);
}
DoWork() takes several seconds to run and I don't really want to put it into a thread, as this code will be used in several places and will probably interact will the Dispatcher thread at various intervals. I've tried calling the Invalidate...() methods, but to no avail. The BeginInvoke() was added to see if the delay would allow the background change to be applied before the logic was called. Typically, the logic would be part of this method. Btw, most of the logic is performed on a different thread and shouldn't block the Dispatcher thread?!
Can someone please help?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
“Dispatcher”线程是 UI 线程。
当您调用
Dispatcher.BeginInvoke((Action) DoWork);
时,您基本上会阻塞 UI 线程,直到DoWork
退出,因为它在 UI 线程上运行。这将阻止 UI 更新,因此您看不到背景变化。
您确实应该考虑将 DoWork 移动到后台线程上,可以直接通过 ThreadPool、BackgroundWorker 或其他方式。这将完全纠正这个问题,并防止您阻塞 UI 线程“几秒钟”(如果您使用调度程序的线程运行它,就会发生这种情况)。
The "Dispatcher" thread is the UI thread.
When you call
Dispatcher.BeginInvoke((Action) DoWork);
, you're basically blocking the UI thread untilDoWork
exits, since it's running on the UI thread.This will prevent the UI from updating, hence you don't see the background change.
You really should consider moving
DoWork
onto a background thread, either via the ThreadPool directly, a BackgroundWorker, or some other means. That would completely correct this problem, and prevent you from blocking the UI thread for a "few seconds" (which will happen if you run this using the Dispatcher's threading).对于线程之间的通信,我们在 WPF 中提供了 Dispatcher 类。
For communication between threads, we have the
Dispatcher
class in WPF.BeginInvoke(..) 方法不会阻塞调用,而只是将一条新消息放入队列中以供调度程序线程处理。在您发布的代码中,您无法保证在 DoWorks 启动之前处理背景颜色更改。
您可以降低 DoWork 调用的优先级,以确保首先更改背景:
但这不是人类已知的最佳解决方案。
更好的办法是在单独的线程中继续执行 DoWork。
上面使用线程方法的示例如下所示:
只需记住将对 UI 元素的所有操作发布到 UI 线程即可。
BeginInvoke(..) method does not block the call but it simply put a new message to the queue to process by dispatcher thread. In the code you posted, you have no guarantee that background color change will processed before DoWorks starts.
You can put lower priority to the DoWork call to be sure that background is changed first:
But this is not the best solution known to the mankind.
Better would be to proceed with DoWork in separate thread.
Above example using thread approach will look like this:
Just remember to post all operations on UI elements to the UI thread.