What's the difference between InvokeAsync and BeginInvoke for WPF Dispatcher
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;}
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 is a difference in method signature:
BeginInvoke(Delegate, Object[])InvokeAsync(Action)
For BeginInvoke()
compiler creates array Object[]
implicitly while for InvokeAsync()
such array is not needed:
IL_0001: ldarg.0IL_0002: call instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher()IL_0007: ldarg.1IL_0008: ldc.i4.0IL_0009: newarr [mscorlib]System.ObjectIL_000e: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::BeginInvoke(class [mscorlib]System.Delegate, object[])IL_0014: ldarg.0IL_0015: call instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher()IL_001a: ldarg.1IL_001b: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::InvokeAsync(class [mscorlib]System.Action)