6

.NET 3.5 和 WPF 中的 Dispatcher 概念与 .NET 2.0 中的后台线程有何不同?

例如,以下语句之间有什么区别:

delegate.Invoke/BeginInvoke

this.dispatcher.Invoke/BeginInvoke
4

4 回答 4

6

调度器可以被认为是一个事件被发送到的队列;调度程序将在 UI 线程上运行并为 UI 执行事件。在 Windows 中,UI 控件只能由创建它们的线程修改,因此对 UI 的任何更改都必须从 UI 线程完成 - 因此这是修改窗口元素的操作必须发送到 UI 的关键原因之一调度员。

反过来,后台线程是与 UI 不同的线程。所以在这些线程之一上运行的任何东西都不会影响或阻塞 UI。

于 2010-03-29T02:36:30.900 回答
2

BeginInvoke 和 Invoke 的概念可以这样想。

  • BeginInvoke 的意思是:“执行此操作并在完成之前返回。我要么不关心返回值,要么您可以在将来的某个时候通过这个地址给我回电。”
  • Invoke 的意思是:“这样做,我会坐在这里等待它完成。”

现在这与调度程序和后台线程的关系完全是另一回事。正如 Justin 所说,每次 UI 线程空闲时,Dispatcher 都会处理一系列要做的事情。在调度程序上调用 BeginInvoke 的后台线程将立即返回,即使调度程序可能还没有开始处理。如果改为使用 Invoke,则后台线程将阻塞,直到 UI 线程完成处理。请注意,在 Silverlight 中,Dispatcher 上没有 Invoke,并且在大多数情况下,您可能不希望在 UI 线程处理工作时阻塞后台线程。

相反,Delegate.BeginInvoke 使用线程池中的工作线程。当您在 UI 线程(或任何线程)上时,您可以在委托上调用 BeginInvoke 和 Invoke。BeginInvoke 将使用一个工作线程来调用委托,使用我上面描述的相同语义。然而,调用不会使用不同的线程。它会简单地在调用线程的上下文中同步调用委托,并在完成时返回。

跨线程使用同步执行时要小心,因为如果您不小心,这通常会导致死锁。

于 2010-03-29T02:45:37.830 回答
0

两种方法调用的操作都将放置在事件队列中,以便在 UI 线程上运行。Invoke 将同步发生并阻塞,直到操作完成,BeginInvoke 将异步发生,允许调用方法继续执行。

于 2010-03-29T10:22:49.233 回答
0

使用调度程序执行长时间运行的操作仍会导致它在 UI 线程上执行,只是优先级与当前操作不同。这里的问题是,通常,您希望长时间运行的操作具有尽可能多的带宽。在调度程序下运行时,您会受到 UI 的限制。

调度程序的目的是将后台线程的锚点返回给 UI,以便您可以例如在操作进度时向 UI 提供更新。

如果您想在后台运行操作并将执行推迟到 UI,请使用 backgroundworker 或新的任务库。使用调度程序将更新编组回 UI。

于 2010-03-29T02:44:31.003 回答