Quelle est la différence entre InvokeAsync et BeginInvoke pour WPF Dispatcher

J’ai remarqué dans .NET 4.5 que WPF Dispatcher avait obtenu un nouvel ensemble de méthodes pour exécuter des choses sur le thread du Dispatcher appelé InvokeAsync . Avant, .NET 4.5, nous avions Invoke et BeginInvoke qui les traitaient respectivement de manière synchrone et asynchrone.

Outre la dénomination et les surcharges légèrement différentes disponibles, existe-t-il des différences majeures entre les BeginInvoke et InvokeAsync ?

Oh, et j’ai déjà vérifié, les deux peuvent être await ed:

 private async Task RunStuffOnUiThread(Action action) { // both of these works fine await dispatcher.BeginInvoke(action); await dispatcher.InvokeAsync(action); } 

Il n’y a pas de différences, car la méthode BeginInvoke appelle une méthode privée LegacyBeginInvokeImpl , dont itslef appelle la méthode privée InvokeAsyncImpl (la méthode utilisée par InvokeAsync ). Donc, en gros, c’est la même chose. Il semble que ce soit un simple refactoring, mais il est étrange que les méthodes BeginInvoke n’aient pas été signalées comme obsolètes.

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; } 

Il y a une différence dans la signature de la méthode:

 BeginInvoke(Delegate, Object[]) InvokeAsync(Action) 

Pour BeginInvoke() compilateur crée implicitement le tableau Object[] alors que pour InvokeAsync() type de tableau n’est pas nécessaire:

 IL_0001: ldarg.0 IL_0002: call instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher() IL_0007: ldarg.1 IL_0008: ldc.i4.0 IL_0009: newarr [mscorlib]System.Object IL_000e: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::BeginInvoke(class [mscorlib]System.Delegate, object[]) IL_0014: ldarg.0 IL_0015: call instance class [WindowsBase]System.Windows.Threading.Dispatcher [WindowsBase]System.Windows.Threading.DispatcherObject::get_Dispatcher() IL_001a: ldarg.1 IL_001b: callvirt instance class [WindowsBase]System.Windows.Threading.DispatcherOperation [WindowsBase]System.Windows.Threading.Dispatcher::InvokeAsync(class [mscorlib]System.Action) 

La gestion des exceptions est différente.

Vous voudrez peut-être vérifier les éléments suivants:

 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(); } 

[Modifier – les deux sont identiques]

À cause de

BeginInvoke fonctionne sur le thread sur lequel le dissortingbuteur a été créé et InvokeAsync fonctionne avec le thread sur lequel le dissortingbuteur est associé.

Cela signifie que si vous devez traiter quelque chose basé sur le thread actuel du répartiteur, vous utiliserez InvokeAsync sinon utilisez BeginInvoke.

EDIT: – mais le commentaire ci-dessus n’a pas de sens car vous ne pouvez pas changer le thread associé du répartiteur une fois qu’il est créé.

D’accord avec ci-dessus mentionne réponse .. merci