2016-07-20 8 views
-2

Die Verwendung von Task.WhenAll hat viele Vorteile, aber es verdoppelt mindestens die LOC erforderlich, um etwas zu schreiben.Task.WhenAll mit weniger Codezeilen

Listing1

var result1 = await SomeLongRunningOperation1().ConfigureAwait(false); 
var result2 = await SomeLongRunningOperation2().ConfigureAwait(false); 
var result3 = await SomeLongRunningOperation3().ConfigureAwait(false); 

Listing2

var result1Task = SomeLongRunningOperation1(); 
var result2Task = SomeLongRunningOperation2(); 
var result3Task = SomeLongRunningOperation3(); 

await Task.WhenAll(
    result1Task, 
    result2Task, 
    result3Task) 
    .ConfigureAwait(false); 

var result1 = result1Task.Result; 
var result2 = result2Task.Result; 
var result3 = result3Task.Result; 

Offensichtlich erwartet Listing1 Die 3-Operationen eine nach der anderen (3 × 10 Sekunden = 30 Sekunden), während Listing2 die 3 Operationen wartet auf die gleiche Zeit (nur 10 Sekunden für alle 3).

Allerdings ist der Code in Listing2 viel länger und schwerer zu lesen.

Meine Frage ist: Ist es möglich, die Logik von Listing2 mit etwas so einfach zu lesen und so kurz wie Listing1 schreiben?

+0

Put "result1Task result2Task result3Task" in Array, und Ihr Code ist kürzer. –

Antwort

1

Wie ich in einem Kommentar sagte, erreicht dies die Parallelität Sie suchen und verwendet weniger Codezeilen als Listing 2:

var result1Task = SomeLongRunningOperation1(); 
var result2Task = SomeLongRunningOperation2(); 
var result3Task = SomeLongRunningOperation3(); 

var result1 = await result1Task.ConfigureAwait(false); 
var result2 = await result2Task.ConfigureAwait(false); 
var result3 = await result3Task.ConfigureAwait(false); 

Es geringfügige Unterschiede im Timing hat - wenn result1 verfügbar ist deutlich bevor result2 oder result3 verfügbar ist, wird es früher zugewiesen. Aber seit Sie await alle 3 Aufgaben (und nichts mit den Ergebnissen tun), werden Sie nicht tatsächlich über die Zuweisung von result3 weitermachen, bis alle drei Aufgaben abgeschlossen sind - genau das, was Sie mit Ihrem WhenAll gefragt haben.

0

Sie könnten Tuple s verwenden, aber Sie müssten Helper-Methoden für verschiedene Aritäten erstellen. Hier ist so eine für 3 Argumente:

public static async Task<Tuple<T1, T2, T3>> WhenAll<T1, T2, T3>(Task<T1> t1, Task<T2> t2, Task<T3> t3) 
{ 
    await Task.WhenAll(t1, t2, t3).ConfigureAwait(false); 
    var result1 = await t1.ConfigureAwait(false); 
    var result2 = await t2.ConfigureAwait(false); 
    var result3 = await t3.ConfigureAwait(false); 
    return Tuple.Create(result1, result2, result3); 
} 

Verbrauch:

var results = await WhenAll(Operation1(), Operation2(), Operation3()); 
var result1 = results.Item1; 

In C# 7 Sie die eingebaute in Tupel Unterstützung nutzen könnten, um die Tupel Elemente genannt werden würde.

0

Wenn Ihr Betrieb alle das gleiche Ergebnis Typ haben, können Sie auch tun:

var task1 = SomeLongRunningOperation1(); 
var task2 = SomeLongRunningOperation2(); 
var task3 = SomeLongRunningOperation3(); 

var results = await Task.WhenAll(task1, task2, task3).ConfigureAwait(false);