Application Dispatcher and Control Dispatcher

2019-02-18 15:05发布

问题:

Assume i have control button with name "button1" and function with name "doSomething". Function "doSomething" is called from another thread.

i have two method to call function doSomething from UI thread.

First, from control button dispatcher

this.button1.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

and Second, from application dispatcher

this.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

The result is same, what is the real different ?

回答1:

The same dispatcher instance is referenced in all controls owned by the same thread. There is no difference.



回答2:

All of UI controls (which were created normally), share the same dispatcher instance. That dispatcher is working on UI thread. If you create some control on backgroud thread, it will create new dispatcher on that thread, and this will not be very good. The best way to avoid most problems with threading and UI controls both in WinForms and WPF is to use System.Threading.SynchronizationContext.Current. The workflow is simple: you get System.Threading.SynchronizationContext.Current while you are on UI thread and save it somewhere (for example in a public static field). Then, whenever you want to run some code on UI thread, you access that persisted SynchronizationContext intance and use its Send or Post methods. It will run you delegates on thread, where SynchronizationContext was achieved (for current case on UI thread). Also it is smart enough, to use the current way of Invoking (message loop for WinForms and dispatcher for WPF) and also if you are already calling from UI thread it will just run your delegate synchronously. Just keep in mind, that you should get SynchronizationContext only after you create your first control on the current UI thread, because SynchronizationContext will be initialized right after that.



回答3:

In most of the case, We have single UI thread. So, It doesn't make difference you call

control.Dispatcher(which comes inherited from DispatcherObject parent of the controls).

or 

Disptacher.Current.

But there are scenarios, where you will end up having multiple dispatchers. So, in that situation, Control.Dispatcher will help as It will find out the current dispatcher to respect Thread Affinity. In this Dispatcher.Current won't help.

One scenario, having dedicated thread(with dispatcher) for displaying busy indicator as default UI thread is busy in rendering large list of controls.

However, with SynchronizationContext is another way to avoid such issues. but what if that context or thread is no longer required or it has been set to null by any other developer. So, It is always wise to go for Control.Dispatcher in my opinion.