I noticed in .NET 4.5 that the WPF Dispatcher had gotten a new set of methods to execute stuff on the Dispatcher's thread called InvokeAsync. Before, .NET 4.5 we had Invoke and BeginInvoke which handled this syncronously and asynchronously respectively.
Besides the naming and the slightly different overloads available, are there any major differences between the BeginInvoke
and the InvokeAsync
methods?
Oh, and I already checked, both can be await
ed:
private async Task RunStuffOnUiThread(Action action) { // both of these works fine await dispatcher.BeginInvoke(action); await dispatcher.InvokeAsync(action); }
BeginInvoke(DispatcherPriority, Delegate, Object) Executes the specified delegate asynchronously at the specified priority and with the specified argument on the thread the Dispatcher is associated with.
Invoke : Executes on the UI thread, but calling thread waits for completion before continuing. Control. BeginInvoke : Executes on the UI thread, and calling thread doesn't wait for completion.
InvokeAsync(Action) Executes the specified Action asynchronously on the thread the Dispatcher is associated with. InvokeAsync(Action, DispatcherPriority) Executes the specified Action asynchronously at the specified priority on the thread the Dispatcher is associated with.
WPF Dispatcher is associated with the UI thread. The UI thread queues methods call inside the Dispatcher object. Whenever your changes the screen or any event executes, or call a method in the code-behind all this happen in the UI thread and UI thread queue the called method into the Dispatcher queue.
The exception handling is different.
You may want to check the following:
private async void OnClick(object sender, RoutedEventArgs e) { Dispatcher.UnhandledException += OnUnhandledException; try { await Dispatcher.BeginInvoke((Action)(Throw)); } catch { // The exception is not handled here but in the unhandled exception handler. MessageBox.Show("Catched BeginInvoke."); } try { await Dispatcher.InvokeAsync((Action)Throw); } catch { MessageBox.Show("Catched InvokeAsync."); } } private void OnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show("Catched UnhandledException"); } private void Throw() { throw new Exception(); }
There are no differences as the BeginInvoke
method calls a private LegacyBeginInvokeImpl
method which itslef calls the private method InvokeAsyncImpl
(the method used by InvokeAsync
). So it's basically the same thing. It seems like it's a simple refactoring, however it's strange the BeginInvoke
methods weren't flagged as obsolete.
BeginInvoke :
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method) { return this.LegacyBeginInvokeImpl(priority, method, null, 0); } private DispatcherOperation LegacyBeginInvokeImpl(DispatcherPriority priority, Delegate method, object args, int numArgs) { Dispatcher.ValidatePriority(priority, "priority"); if (method == null) { throw new ArgumentNullException("method"); } DispatcherOperation dispatcherOperation = new DispatcherOperation(this, method, priority, args, numArgs); this.InvokeAsyncImpl(dispatcherOperation, CancellationToken.None); return dispatcherOperation; }
InvokeAsync :
public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority) { return this.InvokeAsync(callback, priority, CancellationToken.None); } public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken) { if (callback == null) { throw new ArgumentNullException("callback"); } Dispatcher.ValidatePriority(priority, "priority"); DispatcherOperation dispatcherOperation = new DispatcherOperation(this, priority, callback); this.InvokeAsyncImpl(dispatcherOperation, cancellationToken); return dispatcherOperation; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With