使用Dispatcher.Invoke从非主线程更改WPF控件
我最近开始在WPF编程,碰到以下问题。 我不明白如何使用Dispatcher.Invoke()
方法。 我有线程的经验,我已经做了一些简单的Windows窗体程序,我刚刚使用
Control.CheckForIllegalCrossThreadCalls = false;
是的,我知道这是很蹩脚的,但这些都是简单的监控应用程序。
事实上,现在我正在做一个WPF应用程序,在后台检索数据,我开始一个新的线程,使调用检索数据(从networking服务器),现在我想显示在我的WPF表单。 事情是,我不能从这个线程设置任何控制。 甚至没有标签或任何东西。 这怎么解决?
回答评论:
@Jalfp:
所以当我得到这些数据的时候,我在“新步伐”中使用了这个Dispatcher方法? 或者,我应该让一个后台工作人员检索数据,把它放到一个字段,并开始一个新的线程,等待这个字段填充,并呼吁调度员显示检索到的数据到控制?
首先要了解的是,Dispatcher不是devise用于运行长时间阻塞操作(例如从WebServer中检索数据…)。 当您想要运行将在UI线程上执行的操作(例如更新进度条的值)时,可以使用Dispatcher。
你可以做的是在后台工作中检索数据,并使用ReportProgress方法在UI线程中传播更改。
如果你真的需要直接使用Dispatcher,这很简单:
Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => this.progressBar.Value = 50));
japf已经正确回答了。 以防万一,如果你正在看多线行动,你可以写如下。
Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => { this.progressBar.Value = 50; }));
其他想要了解性能的用户的信息:
如果您的代码需要写入高性能,您可以首先检查是否需要通过使用CheckAccess标志的调用。
if(Application.Current.Dispatcher.CheckAccess()) { this.progressBar.Value = 50; } else { Application.Current.Dispatcher.BeginInvoke( DispatcherPriority.Background, new Action(() => { this.progressBar.Value = 50; })); }
请注意,方法CheckAccess()是从Visual Studio 2015中隐藏的,所以只需编写它,而不需要intellisense来显示它。 请注意CheckAccess性能开销(几纳秒的开销)。 只有当你想要保存执行“invoke”所需的微秒时,它才会更好。 而且,当调用方法确定它是否在UI线程中时,总是可以select创build两个方法(on和invoke)。 当你看到调度员的这个方面时,这是罕见的罕见情况。