2009-10-29 110 views
60

我最近开始在WPF中编程并碰到以下问题。我不明白如何使用Dispatcher.Invoke()方法。我在线程经验,我已经做了几个简单的Windows窗体,我只是用使用Dispatcher.Invoke从非主线程更改WPF控件

Control.CheckForIllegalCrossThreadCalls = false; 

是的,我知道这是很蹩脚的,但这些都是简单的监控应用程序。

事实上,现在我正在制作一个WPF应用程序,它在后台检索数据,我从一个新线程开始调用以检索数据(来自Web服务器),现在我想将其显示在我的WPF形成。事情是,我无法从这个线程设置任何控制。甚至没有标签或任何东西。这怎么解决?

答评论:
@Jalfp:
所以我用这个方法调度员在“新胎”时,我得到的数据?或者我应该让后台工作人员检索数据,将其放入一个字段并启动一个等待填充该字段的新线程,并调用调度程序将检索到的数据显示到控件中?

回答

145

首先要了解的是,Dispatcher并非设计用于运行长阻塞操作(例如从WebServer中检索数据...)。当您想要运行将在UI线程上执行的操作时(例如更新进度栏的值),可以使用Dispatcher。

您可以做的是在后台工作中检索数据,并使用ReportProgress方法在UI线程中传播更改。

如果你确实需要直接使用分派器,这是很简单的:

Application.Current.Dispatcher.BeginInvoke(
    DispatcherPriority.Background, 
    new Action(() => this.progressBar.Value = 50)); 
+19

可以摆脱“新的行动(”部分,并简单地使用lambda表达式: DispatcherPriority.Background,()=> this.progressBar.Value = 50 – jrista 2009-10-29 14:55:37

+0

呀不知道为什么,我把一个Action在这里:p – japf 2009-10-29 15:09:00

+0

因此,当我获取数据时,我在“新步伐”中使用这种Dispatcher方法?或者我应该让后台工作人员检索数据,将其放入一个字段并启动一个等待该字段的新线程填写并致电调度员显示检索到的数据到控件? – 2009-10-30 08:17:53

19

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年隐藏所以只写它不期待的智能感知,以显示它。请注意,CheckAccess的性能开销(几纳秒的开销)。当你想要保存执行'invoke'所需的微秒时,它会更好。另外,当调用方法确定它是否在UI线程中时,总是可以选择创建两个方法(on和on,另一个没有)。当你应该关注调度员的这一方面时,这种情况很罕见。

相关问题