How does the Dispatcher开发者_运维问答 concept in .NET 3.5 and WPF differ from the background thread in .NET 2.0 ?
For example what will be difference between statements below:
delegate.Invoke/BeginInvoke
AND
this.dispatcher.Invoke/BeginInvoke
The dispatcher can be thought of as a Queue that events are sent to; a dispatcher will run on the UI thread and execute events for the UI. In windows, UI controls may only be modified by the thread that created them, so any changes to the UI must be done from the UI thread - thus that is one of the critical reasons why operations that modify window elements must be sent to the UI's dispatcher.
A background thread, in turn, is a different thread than the UI. So anything run on one of these threads will not affect or block the UI.
The concept of BeginInvoke and Invoke can be thought of as follows.
- BeginInvoke means: "Do this and return before it completes. I either don't care about the return value or you can call me back at this address at some point in the future."
- Invoke means: "Do this and I'll sit here and wait for it to complete."
Now how this relates to dispatchers and background threads is another matter altogether. As Justin says, the Dispatcher processes a queue of things to do every time the UI thread becomes idle. A background thread that calls BeginInvoke on the dispatcher will return immediately even though the dispatcher may not have gotten around to processing. If Invoke had been used instead, the background thread would block until the UI thread completed processing. Note that in Silverlight, there is no Invoke on the Dispatcher and in most cases you probably don't want your background thread blocking while the UI thread is processing work.
Conversely, Delegate.BeginInvoke uses worker threads in the thread pool. When you're on the UI thread (or any thread really) you can call BeginInvoke and Invoke on a delegate. BeginInvoke will use a worker thread to call the delegate using the same semantics I described above. Invoke, however, would not use a different thread. It would simply invoke the delegate synchronously in the context of the calling thread and return when completed.
Be careful when using synchronous execution across threads though as this often results in deadlocks if you're not very careful.
Using the dispatcher to execute a long-running operation still causes it to execute on the UI thread, just at a different priority than the current operation. The problem here is that usually, you want your long-running operation to have as much bandwidth as is feasible. Running under the dispatcher, you're throttled by the UI.
The point of the dispatcher is to give an anchor to a background thread back to the UI so that you can for example provide an update to the UI on the progress of your operation.
If you want to run an operation in the background and defer execution to the UI, use a backgroundworker or the new task library. Use the dispatcher to marshal updates back to the UI.
The operations invoked by both methods will be placed on the event queue to be run on the UI thread. Invoke will occur synchronously and will block until the operation completes, BeginInvoke will occur asyncronously allowing the calling method to continue executing.
精彩评论