Dispatcher与后台线程有何不同?

时间:2010-03-29 02:25:27

标签: wpf multithreading delegates wpf-controls dispatcher

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

例如,下面的陈述之间会有什么区别:

delegate.Invoke/BeginInvoke

AND

this.dispatcher.Invoke/BeginInvoke

4 个答案:

答案 0 :(得分:6)

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

反过来,后台线程是与UI不同的线程。因此,在其中一个线程上运行的任何内容都不会影响或阻止UI。

答案 1 :(得分:2)

BeginInvoke和Invoke的概念可以被认为如下。

  • BeginInvoke表示:“执行此操作并在完成之前返回。我要么不关心返回值,要么可以在将来的某个时刻回复此地址。”
  • 调用意味着:“这样做,我会坐在这里等待它完成。”

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

相反,Delegate.BeginInvoke使用线程池中的工作线程。当你在UI线程(或任何线程)上时,你可以在委托上调用BeginInvoke和Invoke。 BeginInvoke将使用工作线程使用与上述相同的语义来调用委托。但是,Invoke不会使用不同的线程。它只是在调用线程的上下文中同步调用委托,并在完成时返回。

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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