【发布时间】:2019-07-07 06:19:43
【问题描述】:
我正在开发一个 WPF 应用程序。
在服务器上,有许多线程/任务会抛出 UI 注册到的操作。
侦听器在引发操作的同一线程上调用,因此在 UI 的侦听器中,当我想更新 UI 元素时,我需要通过 Application.Current.Dispatcher.BeginInvoke(行动) 或 Application.Current.Dispatcher.Invoke(action)。
当大量线程引发这些操作时,会多次调用 Application.Current.Dispatcher.Invoke(action)(我现在使用 Invoke),有时在几毫秒的范围内。
过了一会儿,如果我在之前放了一个断点 Application.Current.Dispatcher.Invoke 以及动作本身内部的断点,连接到 UI 线程 Dispatcher 以及实际开始执行的实际动作可能需要几秒钟,甚至超过 5 秒。
另一方面,为什么 Application.Current.Dispatcher.BeginInvoke(action) 会解决我的问题?
我的意思是,我们只有一个 UI 线程,所以 BeginInvoke 方法只会将这些操作放在一个队列中,而动作 X 仍然需要很长时间才能发生。我认为这不会使任何应该在 UI 线程上运行的操作启动得更快(当 UI 线程忙时)。我说的对吗?
我的目的是:
private void UpdateScreen(){
Application.Current.Dispatcher.Invoke(() =>
{
OnPropertyChanged(() => Time);
OnPropertyChanged(() => TimeFormatted);
OnPropertyChanged(() => SliderText);
});}
我希望动作开始执行行
OnPropertyChanged(() => Time);
OnPropertyChanged(() => TimeFormatted);
OnPropertyChanged(() => SliderText);
当我到达方法 UpdateScreen() 时尽快
如果 BeginInvoke 实际上更好,为什么会比 Invoke 更好?
【问题讨论】:
-
Dispatcher.Invoke() 是一个严重的设计错误。只有当您需要返回值时才需要,如果您这样做了,那么您就隐藏了线程竞争错误。遗憾的是直到 UWP 微软才意识到这个错误,CoreDispatcher 只有一个 RunAsync() 方法。
标签: c# wpf multithreading