确保在WPF中的UI线程上运行

时间:2010-03-04 20:57:13

标签: .net wpf invoke dispatcher

我正在构建一个WPF应用程序。我正在与服务器端进行一些异步通信,我在客户端上使用Prism进行事件聚合。这两件事导致产生新的线程,而不是UI线程。如果我尝试在这些回调和事件处理程序线程上执行“WPF操作”,那么世界将会崩溃,现在它已经开始了。

首先,我遇到了尝试在服务器回调中创建一些WPF对象的问题。我被告知线程需要在STA模式下运行。现在我正在尝试更新Prism事件处理程序中的一些UI数据,我被告知:

  

调用者无法访问此线程,因为其他线程拥有该线程。

因此; 在WPF中解决问题的关键是什么?我已经在this MSDN post中阅读了WPF调度程序。我开始明白了,但我还没有巫师。

  1. 当我需要运行一些我不确定会在UI线程上调用的东西时,总是使用Dispatcher.Invoke的关键是什么?
  2. 如果它实际上是在UI线程上调用的,它是否重要,我还是做Dispatcher.Invoke?
  3. Dispatcher.Invoke =同步。 Dispathcher.BeginInvoke = async?
  4. Dispatcher.Invoke会请求UI线程,然后停止等待吗?是不良做法和风险较低的程序?
  5. 我如何获得调度员? Dispatcher.CurrentDispatcher会不会给我代表UI线程的调度程序?
  6. 是否存在多个Dispatcher,或者“Dispatcher”是否与应用程序的UI线程基本相同?
  7. 与BackgroundWorker的交易是什么?我什么时候使用它呢?我认为这总是异步的?
  8. 在UI公寓模式下运行在UI线程上运行的所有内容(通过调用)吗?即如果我有需要在STA模式下运行的东西 - Dispatcher.Invoke会足够吗?
  9. 有人想为我清理事情吗?任何相关的建议等?谢谢!

1 个答案:

答案 0 :(得分:37)

逐一回答你的每个问题:

  1. 不完全;你应该只在必要时调用UI线程。见#2。
  2. 是的,这很重要。你不应该只是自动Invoke一切。关键是只在必要时才调用UI线程。为此,您可以使用Dispatcher.CheckAccess方法。
  3. 这是对的。
  4. 同样正确,是的,您确实存在响应程度较低的风险。大多数情况下,你不会看到严重的性能损失(我们谈论的是上下文切换的毫秒数),但是如果需要你应该只Invoke。话虽如此,在某些方面它是不可避免的,所以不,我不会说这是不好的做法。这只是你不时会遇到的问题的一种解决方案。
  5. 在我看过的每一个案例中,我都使用了Dispatcher.CurrentDispatcher。对于复杂的情况,这可能还不够,但我(个人)还没有看到它们。
  6. 不完全正确,但这种思路不会造成任何伤害。我这样说吧:Dispatcher 可用于访问应用程序的UI线程。但它本身并不是UI线程。
  7. BackgroundWorker通常在您执行耗时的操作时使用,并且希望在后台运行该操作时维护响应式UI。通常,您不使用Invoke的BackgroundWorker 而不是,而是将BackgroundWorker Invoke结合使用。也就是说,如果您需要更新BackgroundWorker中的某个UI对象,则可以调用UI线程,执行更新,然后返回到原始操作。
  8. 是。根据定义,WPF应用程序的UI线程必须在单线程单元中运行。
  9. 关于BackgroundWorker有很多话要说,我相信很多问题已经付诸实施,所以我不会深入探讨。如果您感到好奇,请查看MSDN page for BackgroundWorker class