2015-08-20 5 views
24

In Bezug auf die Leistung, werden diese 2 Methoden GetAllWidgets() und GetAllFoos() parallel laufen lassen?mehrere erwartet vs Task.WaitAll - gleichwertig?

Gibt es einen Grund, einen über den anderen zu verwenden? Es scheint eine Menge hinter den Kulissen mit dem Compiler zu geschehen, daher finde ich es nicht klar.

============= MethodA: Verwenden mehrerer erwartet ======================

public async Task<IHttpActionResult> MethodA() 
{ 
    var customer = new Customer(); 

    customer.Widgets = await _widgetService.GetAllWidgets(); 
    customer.Foos = await _fooService.GetAllFoos(); 

    return Ok(customer); 
} 

=============== MethodB: Mit Task.WaitAll =====================

public async Task<IHttpActionResult> MethodB() 
{ 
    var customer = new Customer(); 

    var getAllWidgetsTask = _widgetService.GetAllWidgets(); 
    var getAllFoosTask = _fooService.GetAllFos(); 

    Task.WaitAll(new List[] {getAllWidgetsTask, getAllFoosTask}); 

    customer.Widgets = getAllWidgetsTask.Result; 
    customer.Foos = getAllFoosTask.Result; 

    return Ok(customer); 
} 

=================================

+0

In Ihrem ersten Beispiel werden die beiden Methoden nacheinander aufgerufen und in der zweiten werden sie parallel ausgeführt, also sind sie nicht gleichwertig. Außerdem blockieren Sie bei der zweiten Methode die Ausführung der Aufgaben. –

+0

MethodeA führt '_fooService.GetAllFoos()' nur dann aus, wenn '_widgetService.GetAllWidgets()' beendet ist, führt methodB das aus, wenn der nicht abgeschlossene Task von '_fooService.GetAllFoos()' zurückkommt. –

Antwort

37

Die erste Option führt die beiden Vorgänge nicht gleichzeitig aus. Es wird das erste ausführen und auf sein Ende warten, und erst dann das zweite.

Die zweite Option führt beide gleichzeitig aus, wartet aber synchron auf sie (d. H. Blockiert einen Thread).

Sie sollten beide Optionen nicht verwenden, da die erste langsamer als die zweite und die zweite einen Thread ohne Notwendigkeit abschließt.

Sie sollten für beide Operationen mit Task.WhenAll asynchron warten:

public async Task<IHttpActionResult> MethodB() 
{ 
    var customer = new Customer(); 

    var getAllWidgetsTask = _widgetService.GetAllWidgets(); 
    var getAllFoosTask = _fooService.GetAllFos(); 

    await Task.WhenAll(getAllWidgetsTask, getAllFoosTask); 

    customer.Widgets = await getAllWidgetsTask; 
    customer.Foos = await getAllFoosTask; 

    return Ok(customer); 
} 

Beachten Sie, dass nach Task.WhenAll bereits abgeschlossen beide Aufgaben abgeschlossen, so sie sofort abgeschlossen warten.

+1

Danke. Das habe ich gebraucht. Das ".Result" hat mich gestört und deine Antwort vermeidet das. – vidalsasoon

+0

@vidalsasoon sicher .. jederzeit. – i3arnon

+2

Sie können '' task.WhenAll (getAllWidgetsTask, getAllFoosTask); '' auch vollständig überspringen und nur auf Aufgaben warten (starten Sie einfach die zweite Aufgabe, bevor Sie zuerst warten). – kwesolowski

0

Nur Ihre zweite Option wird sie parallel ausführen . Ihre erste wird nacheinander auf jeden Anruf warten.

0

Sobald Sie die asynchrone Methode aufrufen, wird die Ausführung gestartet. Ob es auf dem aktuellen Thread ausgeführt wird (und somit synchron ausgeführt wird) oder Async ausgeführt wird, kann nicht bestimmt werden.

Also, in Ihrem ersten Beispiel wird die erste Methode Arbeit zu tun, aber dann stoppt Sie künstlich den Fluss des Codes mit dem warten. Und somit wird die zweite Methode nicht aufgerufen, bevor die erste ausgeführt wird.

Das zweite Beispiel ruft beide Methoden auf, ohne den Fluss mit einer Wartezeit zu stoppen. Daher werden sie möglicherweise parallel ausgeführt, wenn die Methoden asynchron sind.

6

Kurze Antwort: Nein.

Task.WaitAll blockiert, await kehrt die Aufgabe, sobald er auftritt und registriert den verbleibenden Teil der Funktion und Fortsetzung.

Die "bulk" wartende Methode, die Sie suchten, ist Task.WhenAll, die tatsächlich eine neue Task erstellt, die beendet wird, wenn alle Aufgaben, die an die Funktion übergeben wurden, erledigt sind.

Wie so: await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});

, die für die Sperr Angelegenheit.

Auch Ihre erste Funktion führt beide Funktionen nicht parallel aus.Um diese Arbeit zu bekommen mit await würden Sie haben, so etwas schreiben:

var widgetsTask = _widgetService.GetAllWidgets(); 
var foosTask = _fooService.GetAllWidgets(); 
customer.Widgets = await widgetsTask; 
customer.Foos = await foosTask; 

Dies wird das erste Beispiel machen sehr ähnlich zu handeln, um die Task.WhenAll Methode.