2010-03-04 59 views
35

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

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

调用者无法访问此线程,因为不同的线程拥有它。

所以; 在WPF中找对事物的关键是什么?我已经在this MSDN post的WPF Dispatcher上读过。我开始明白了,但我还不是巫师。

  1. 当我需要运行一些我不确定的东西时,总是使用Dispatcher.Invoke的关键是在UI线程上调用吗?
  2. 它是否真的在UI线程上调用它,并且我仍然执行Dispatcher.Invoke?
  3. Dispatcher.Invoke =同步。 Dispathcher.BeginInvoke =异步?
  4. 请问Dispatcher.Invoke请求UI线程,然后停下来等待它?它是不好的做法和风险较低的应对方案?
  5. 无论如何,我该如何获得调度员?请问Dispatcher.CurrentDispatcher总是给我代表UI线程的调度程序?
  6. 是否存在多个Dispatcher,或者“Dispatcher”与应用程序的UI线程基本相同?
  7. 和BackgroundWorker有什么关系?我什么时候用这个呢?我认为这总是异步?
  8. 运行在UI线程上的所有东西(通过被调用)是否在STA公寓模式下运行?即如果我有需要在STA模式下运行的东西 - Dispatcher.Invoke是否足够?

有人想为我清理一些东西吗?任何相关的建议,等等?谢谢!

回答

37

去在您的每一个问题,一个接一个:

  1. 不太;你应该只在必要时调用UI线程。见#2。
  2. 是的,这很重要。你不应该只是自动Invoke的一切。关键是只在必要时调用UI线程。为此,您可以使用Dispatcher.CheckAccess方法。
  3. 这是正确的。
  4. 也是正确的,是的,你确实会面临程序响应性较差的风险。大多数情况下,您不会看到严重的性能下降(我们正在谈论上下文切换的毫秒数),但如果需要,您应该只有Invoke。这就是说,在某些方面它是不可避免的,所以不,我不会说这是不好的做法。这只是解决您偶尔会遇到的问题的一种解决方案。
  5. 在任何情况下,我已经看到,我已经与Dispatcher.CurrentDispatcher。对于复杂情况,这可能还不够,但我(个人)没有看到它们。
  6. 不完全正确,但这种思路不会造成任何伤害。让我这样说:Dispatcher可以用于获取应用程序的UI线程的访问权限。但它本身并不是UI线程。
  7. BackgroundWorker通常用于您有耗时操作并希望在后台运行该操作时维护响应式用户界面的情况。通常,您不使用调用的BackgroundWorker ,而使用,而是使用BackgroundWorker Invoke一起使用。也就是说,如果您需要更新BackgroundWorker中的某个UI对象,则可以调用UI线程,执行更新,然后返回到原始操作。
  8. 是的。根据定义,WPF应用程序的UI线程必须在单线程的公寓中运行。

关于BackgroundWorker有很多可以说,我敢肯定很多问题已经提到它了,所以我不会深入了解太多。如果您好奇,请查看MSDN page for BackgroundWorker class

+0

非常感谢查理!这真的是澄清和帮助! – stiank81 2010-03-04 21:47:25

+0

向列表中添加了第8个问题。我希望你可以更新你的答案,包括它:-) – stiank81 2010-03-04 22:42:50

+0

哈哈 - 编辑回答你的最后一个问题。 – Charlie 2010-03-04 23:16:33