2015-08-24 5 views
9

Was sind die Unterschiede zwischen diesen beiden Methoden, die das gleiche zu tun scheint? Kann es auch mit Async gemacht werden/warten?C# Unterschiede zwischen Ergebnis und ContinueWith

public Task<int> TaskMaxAsync1 (Task<int>[] my_ints) 
{ 
    return Task.WhenAll(my_ints) 
    .ContinueWith (x => x.Result.Where (i => i%2 != 0).Max()) ; 
} 

public Task<int> TaskMaxAsync2 (Task<int>[] my_ints) 
{ 
    var numbers = Task.WhenAll(my_ints).Result ; 
    return Task.FromResult(numbers.Where(i => i%2 != 0).Max()) ; 
} 
+1

Ein Unterschied wäre, dass derjenige mit '.Result' zu Deadlocks anfällig ist - http://stackoverflow.com/questions/17248680/await-works- But-Calling-Task-Ergebnis-hängt-Deadlocks –

+0

@ LasseV.Karlsen Sie beide verwenden .Result – TheLethalCoder

+5

Agh, ja, ok, lassen Sie mich umschreiben. Der, der '.Result' außerhalb von 'ContinueWith' verwendet (d. H.der zweite) ist anfällig für Deadlocking. Der einzige Ort, an dem es sicher ist, ".Result" zu lesen, stammt von einer Aufgabe, die garantiert abgeschlossen wurde. Das Lesen von '.Result' aus einer noch nicht abgeschlossenen Aufgabe kann zu einem Deadlock führen. –

Antwort

6

Unterschiede zwischen Ergebnis und ContinueWith

Result wird synchron blockieren, bis die Aufgabe abgeschlossen ist, und Ausnahmen in einer AggregateException wickeln.

ContinueWith registriert einen Rückruf mit der Aufgabe und ruft diesen Rückruf auf, wenn die Aufgabe abgeschlossen ist.

Bei asynchronem Code sollten sowohl Result als auch ContinueWith durch await ersetzt werden.

Kann es auch mit async/warten?

Sicher, wie folgt aus:

public async Task<int> MaxAsync(Task<int>[] my_ints) 
{ 
    int[] ints = await Task.WhenAll(my_ints); 
    return ints.Where(i => i % 2 != 0).Max(); 
} 
7

Was sind die Unterschiede zwischen diesen beiden Methoden, die die Gleiche zu tun scheint?

Der Unterschied besteht darin, dass die erstere liefert eine heiße Aufgabe an die Anrufer, während letztere synchron Blöcke, dann wieder hüllt das Ergebnis in einem TaskTask.FromResult verwenden. Letzteres ist auch ein häufiger Fall für Deadlocks, wenn Sie in einer Umgebung mit einer benutzerdefinierten SynchronizationContext ausgeführt werden.

Kann es auch mit async/warten?

Ja, es kann:

public async Task<int> MaxAsync(Task<int>[] myInts) 
{ 
    int[] results = await Task.WhenAll(myInts); 
    return results.Max(i => i % 2 != 0 ? i : (int?)null) ?? 0; 
} 
3

task0.Result blockiert und warten synchron für task0 zu vervollständigen, während task1.ContinueWith nicht für task1 abgeschlossen warten aber gibt ein neues Task (das wird ausgeführt, wenn task1 abgeschlossen ist) sofort.

Also, die beiden Methoden in Ihrem Beispiel verhalten sich nicht gleich. Wenn in der zweiten Methode my_ints nicht alle ausgeführt wurden, wenn sie an die Methode WhenAll übergeben wurden, blockiert die .Result den aufrufenden Thread synchron für jede lange Zeit, die alle Aufgaben innerhalb von my_ints benötigen, um zu beenden, und wenn einige von ihnen auslösen Ausnahme, TaskMaxAsync2 wirft.

Die erste Methode wird jedoch sofort zurückgegeben my_ints würde nie beenden oder Ausnahme auslösen.

Verwandte Themen