2012-11-16 12 views
50

Ich bemerkte in .NET 4.5, dass die WPF Dispatcher eine neue Reihe von Methoden zum Ausführen von Sachen auf dem Dispatcher-Thread namens InvokeAsync erhalten haben. Vor .NET 4.5 hatten wirund BeginInvoke, die dies syncronously und asynchron jeweils behandelten.Was ist der Unterschied zwischen InvokeAsync und BeginInvoke für WPF Dispatcher

Abgesehen von der Namensgebung und den leicht unterschiedlichen Überladungen, gibt es große Unterschiede zwischen den Methoden BeginInvoke und InvokeAsync?

Oh, und ich bereits geprüft, können beide await ed sein:

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

Antwort

40

Es gibt keine Unterschiede, wie die BeginInvoke Methode eine private LegacyBeginInvokeImpl Methode aufruft, die itslef die private Methode ruft InvokeAsyncImpl (die Methode von InvokeAsync). Es ist also im Grunde dasselbe. Es scheint, als wäre es ein einfaches Refactoring, aber es ist seltsam, dass die Methoden BeginInvoke nicht als veraltet markiert wurden.

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

Zur Zeit bekomme ich unbehandelte Ausnahmen wie erwartet mit BeginInvoke (sowohl DispatcherUnh andledException für den Dispatcher und AppDomain.CurrentDomain.UnhandledException), aber nicht behandelte Ausnahmen in InvokeAsync werden stillschweigend verschluckt. Wenn Sie die Aufgabe von InvokeAsync mit einer Ausnahmefunktion ausführen, scheint dies ein gültiges Problem zu sein. – Lamarth

+2

'BeginInvoke' ist nach dem [" Asynchronous Programming Model "] (https://msdn.microsoft.com/en-us/library/ms228963 (v = vs.110) .aspx) in .NET, das' BeginSomething verwendet 'und' EndSomething' Methoden für asynchrone Operationen. Vermutlich wurde dies deshalb nicht als veraltet oder veraltet bezeichnet. Abgesehen davon, dass die 'Begin' /' End'-Konvention für die Verwendung von 'IAsyncResult' gedacht ist, und' BeginInvoke' nicht, gibt es auch kein 'EndInvoke', so dass es an erster Stelle überflüssig war. – sidbushes

-1

[Edit - beide gleich sind]

Thereotically

BeginInvoke Werke im Thread, auf dem der Dispatcher erstellt wurde und InvokeAsync mit dem Thread arbeitet, dem der Dispatcher zugeordnet ist.

Das bedeutet, wenn Sie etwas basierend auf dem aktuellen Thread des Dispatchers verarbeiten müssen, verwenden Sie das InvokeAsync, andernfalls verwenden Sie BeginInvoke.

EDIT: - aber oben Kommentar ist bedeutungslos wie Sie den zugehörigen Thread des Dispatcher nicht ändern können, sobald es erstellt wird.

Vereinbaren Sie mit oben erwähnt Antwort .. Dank

+0

Könnten Sie bitte einige Referenzen angeben? –

+0

Ich würde auch interessiert sein, da der Code, der dank ILSpy abgerufen wird, keine Unterschiede zwischen den beiden Methoden zeigt – Sisyphe

+2

Ich glaube nicht, dass das stimmt. MSDN sagt "Executes ... auf dem Thread, dem der Dispatcher ** ** zugeordnet ist" auf etwa der Hälfte der "BeginInvoke" -Methodenüberladungen und "Executes ... auf dem Thread, auf dem der Dispatcher ** ** erstellt wurde" auf der anderen Hälfte. Ich bin mir ziemlich sicher, dass es einfach dasselbe bedeutet. – Clemens

11

Es gibt einen Unterschied in der Methode Unterschrift:

:

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

Für BeginInvoke() Compiler-Array ist nicht erforderlich Object[] implizit während für InvokeAsync() solche Anordnung schafft

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) 
Verwandte Themen