WPF/线程:静态调度程序与控件上的调度程序有何不同?

11

我在调度程序方面有点困惑。比如我在一个后台线程中执行某个长时间操作,我想要更新ui线程,我知道可以通过调度程序来实现。我的问题是,我应该静态地调用调度程序吗,比如 Dispatcher.BeginInvoke(mywork) ... 还是在我想要更新的控件上调用:mytextbox.Dispatcher.BeginInvoke(mywork)

3个回答

17
值得注意的是调用Dispatcher.BeginInvoke不是静态调用:它是一个隐式的this.Dispatcher.BeginInvoke。如果你可以使用这个调用,你很可能已经在控件或窗口中编写了代码。在这种情况下,通常情况下每个应用程序都有一个UI线程,所以你可能可以安全地调用任何一个。
实际的静态调用将是Dispatcher.CurrentDispatcher.BeginInvoke,这并不是你想要调用的(请参见我的评论Hasan Khan的答案为什么)。 编辑:调用Application.Current.Dispatcher并不是一件坏事。(为了明确起见,它是一个实例属性,而不是静态的——在一个静态/单例实例上被调用)。该属性将返回创建应用程序的线程的Dispatcher,通常情况下也是创建UI的线程——因此Application.Current.Dispatcher返回与myWindow.Dispatcher相同的Dispatcher。
静态调用Dispatcher.CurrentDispatcher(我警告过的)会返回从其调用的线程的Dispatcher。如果你从后台线程调用它,你会得到一个专门为该线程创建的新的Dispatcher——这通常不是想要的。

为什么使用 Application.Current.Dispatcher 是一个不好的主意?我在我的应用程序中使用它,到目前为止没有任何问题。它只需要调用 Application().Run() - Aphex
@Aphex:我已经作为编辑回答了,因为我无法在评论中适应它 - 但是Application.Current.Dispatcher没有任何问题(我也没有说过有问题)。 Application.Current.DispatcherDispatcher.CurrentDispatcher的行为非常不同! - Dan Puzey
有时候使用Application.Current.Dispatcher是不安全的(虽然很少见),例如在WinForms(或任何非WPF)应用程序中托管WPF控件(Application.Current为null)或在同一应用程序中拥有多个UI线程(共享应用程序资源会有很多问题,但这种情况仍然存在)。因此,最安全的方法是使用control.Dispatcher。 - Aloraman

1

首先,我认为理解Dispatcher的重要性在于它不是设计用来处理大型后台操作的。它被设计用来在对象的UI线程上排队工作。这里有一篇值得阅读的MSDN文章,介绍了.NET线程模型和Dispatcher

可以说实现Dispatcher.BeginInvoke方法的标准方式是在控件上调用它:

startStopButton.Dispatcher.BeginInvoke(
    DispatcherPriority.Normal, new NextPrimeDelegate(CheckNextNumber)
);

希望这能有所帮助!

0

虽然在大多数情况下,使用DispatcherObject.Dispatcher(所有依赖对象和控件都继承自DispatcherObject等)或Application.Current.Dispatcher是正确的做法,因为通常只有一个UI线程,但可能会存在多个UI线程,不同的窗口可以使用不同的调度程序。在这种情况下,重要的是使用其调度程序更新控件。它存储在其Dispatcher属性中(从DispatcherObject继承),此窗口中的任何其他控件和窗口本身。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接