调度程序与后台线程有何区别?

6

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

例如,下面两个语句有何不同:

delegate.Invoke/BeginInvoke

AND

this.dispatcher.Invoke/BeginInvoke
4个回答

6
调度程序可以被认为是一个事件队列,事件将被发送到其中;调度程序将在UI线程上运行并执行UI的事件。在Windows中,UI控件只能由创建它们的线程修改,因此对UI的任何更改都必须从UI线程完成 - 因此这是修改窗口元素的操作必须发送到UI的调度程序的关键原因之一。
另一方面,后台线程是与UI不同的线程。因此,在其中一个线程上运行的任何内容都不会影响或阻塞UI。

2
BeginInvoke和Invoke的概念可以理解为:
- BeginInvoke表示:“执行此操作并在其完成之前返回。我不关心返回值,或者您可以在将来某个时间点调用我的回调函数。” - Invoke表示:“执行此操作,并等待它完成。”
现在,这与调度程序和后台线程的关系是另一回事了。正如Justin所说,调度程序会在UI线程变为空闲时处理要做的事情队列。在后台线程上调用BeginInvoke时,即使调度程序可能还没有开始处理,该线程也会立即返回。如果使用Invoke,则后台线程将阻塞,直到UI线程完成处理。请注意,在Silverlight中,调度程序上没有Invoke,在大多数情况下,您可能不希望在UI线程处理工作时阻塞后台线程。
相反,Delegate.BeginInvoke使用线程池中的工作线程。当您在UI线程(或任何线程)上调用委托的BeginInvoke和Invoke时,BeginInvoke将使用工作线程使用我上面描述的相同语义调用委托。但是,Invoke不会使用不同的线程。它只是在调用线程的上下文中同步调用委托,并在完成后返回。
但是,跨线程使用同步执行时要小心,因为如果不小心,这通常会导致死锁。

0

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

调度程序的目的是为后台线程提供返回到UI的锚点,以便例如提供有关操作进度的UI更新。

如果要在后台中运行操作并将其推迟执行到UI,请使用BackgroundWorker或新的任务库。使用调度程序将更新马歇尔回到UI。


0
由两种方法调用的操作将被放置在事件队列上,在 UI 线程上运行。Invoke 将同步发生,并且将阻止,直到操作完成;而 BeginInvoke 将异步发生,允许调用方法继续执行。

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