WPF/threading: Dispatcher static vs Dispatcher on a control?
I'm a bit confused in terms of the dispatcher. Say I'm on a background thread doing some kind of long operation. I'd like to update the ui thread I understand I do this through the dispatcher. My question is, do i call the dispatcher statically like: Dispatcher.BeginInvoke(mywork) ... Or on the control i want to update: mytextbox.Dispat开发者_C百科cher.BeginInvoke(mywork)
It's worth noting that calling Dispatcher.BeginInvoke
isn't a static call: it's an implicit this.Dispatcher.BeginInvoke
. If you can use this call, you're likely writing your code from within a control or window already. In that case, you're probably safe to call either since most of the time there will be one UI thread per application.
The actual static call would be Dispatcher.CurrentDispatcher.BeginInvoke
, which is not something you want to call (see my comment on Hasan Khan's answer for why).
EDIT: Calling Application.Current.Dispatcher
is not a bad thing. (And, for clarity, it's an instance property, not a static - being called on a static/singleton instance of Application
.) This property will return the Dispatcher for the thread that the app was created with, and typically that's the thread that the UI is created on aswell - so Application.Current.Dispatcher
returns the same Dispatcher as myWindow.Dispatcher
would.
The static call Dispatcher.CurrentDispatcher
(that I warned against) returns a Dispatcher for the thread you call it from. If you call it from a background thread, you'll get a new Dispatcher created especially for that thread - which often isn't what's wanted.
First I think it is important to understand, that the Dispatcher
is not designed to handle big background operations. It is designed to queue work on the UI thread of an object. Here is a worthwhile MSDN article about the .NET threading model and Dispatcher
:
- Threading Model, Overview and the Dispatcher
Saying that the standard way of implementing the Dispatcher.BeginInvoke
method would be to call it on the control:
startStopButton.Dispatcher.BeginInvoke(
DispatcherPriority.Normal, new NextPrimeDelegate(CheckNextNumber)
);
Hope that helps!
While in most cases using either DispatcherObject.Dispatcher
(all dependency objects and controls inherit from DispatcherObject
, among others) or Application.Current.Dispatcher
is the right thing to do, as there's usually only one UI thread, there can be multiple UI threads and different windows can use different dispatchers. In that case, it's important to update the control using its dispatcher. It's stored in in its Dispatcher
property (inherited from DispatcherObject
), any other control in this window and the window itself.
精彩评论