wake-up-neo.com

mehrere erwartet gegen Task.WaitAll - gleichwertig?

Werden diese beiden Methoden in Bezug auf die Leistung GetAllWidgets() und GetAllFoos() parallel ausgeführt?

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

============== MethodA: Verwenden mehrerer Vorhersagen =======================

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

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

    return Ok(customer);
}

================ MethodB: Verwenden von 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);
}

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

40
vidalsasoon

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

Die zweite Option führt beide gleichzeitig aus, wartet jedoch synchron auf sie (d. H. Während sie einen Thread blockiert).

Sie sollten nicht beide Optionen verwenden, da die erste langsamer abläuft als die zweite und die zweite einen Thread ohne Notwendigkeit blockiert.

Sie sollten asynchron mit Task.WhenAll auf beide Operationen 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 Abschluss von Task.WhenAll beide Aufgaben bereits erledigt sind.

68
i3arnon

Kurze Antwort: Nein.

Task.WaitAll blockiert, await gibt die Task zurück, sobald sie gefunden wird, und registriert den verbleibenden Teil der Funktion und die Fortsetzung.

Die "Massen" -Wartemethode, nach der Sie gesucht haben, ist Task.WhenAll, die tatsächlich eine neue Task erstellt, die beendet wird, wenn alle an die Funktion übergebenen Aufgaben abgeschlossen sind.

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

Das ist für die Sperrsache.

Auch Ihre erste Funktion führt beide Funktionen nicht parallel aus. Um dies mit await zum Laufen zu bringen, müssten Sie etwas schreiben:

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

Dadurch wird das erste Beispiel der Task.WhenAll-Methode sehr ähnlich.

13
Nitram

Nur Ihre zweite Option führt sie parallel aus. Ihr erster wird nacheinander bei jedem Anruf warten.

0
nvoigt

Sobald Sie die async-Methode aufrufen, wird sie ausgeführt. Ob es auf dem aktuellen Thread ausgeführt wird (und somit synchron ausgeführt wird) oder asynchron läuft, kann nicht festgestellt werden. 

In Ihrem ersten Beispiel beginnt also die erste Methode mit der Arbeit, aber dann wird der Fluss des Codes künstlich mit dem Abwarten beendet. Daher wird die zweite Methode nicht aufgerufen, bevor die erste Ausführung abgeschlossen ist.

Das zweite Beispiel ruft beide Methoden auf, ohne den Fluss mit einem Abwarten zu stoppen. Sie werden daher möglicherweise parallel ausgeführt, wenn die Methoden asynchron sind. 

0
Kasper Holdum