wake-up-neo.net

WaitAll vs WhenAll

Was ist der Unterschied zwischen Task.WaitAll() und Task.WhenAll() aus dem asynchronen CTP? Können Sie einen Beispielcode bereitstellen, um die verschiedenen Anwendungsfälle zu veranschaulichen?

290
Yaron Levi

Task.WaitAll blockiert den aktuellen Thread, bis alles abgeschlossen ist.

Task.WhenAll gibt ein Task zurück, das die Aktion des Wartens darstellt, bis alles abgeschlossen ist.

Das bedeutet, dass Sie bei einer asynchronen Methode Folgendes verwenden können:

await Task.WhenAll(tasks);

... was bedeutet, dass Ihre Methode fortgesetzt wird, wenn alles abgeschlossen ist, Sie aber bis zu diesem Zeitpunkt keinen Thread zum Herumhängen binden.

444
Jon Skeet

Während JonSkeets Antwort den Unterschied auf eine für mich typische Weise erklärt, ist der größte praktische Unterschied Ausnahmebehandlung. EDIT: Einverstanden - es ist nicht der größte praktische Unterschied, es ist ein Unterschied.

Task.WaitAll Löst ein AggregateException aus, wenn eine der Aufgaben ausgelöst wird, und Sie können alle ausgelösten Ausnahmen untersuchen. Das await in await Task.WhenAll Packt das AggregateException aus und gibt nur die erste Ausnahme zurück.

Wenn das folgende Programm mit await Task.WhenAll(taskArray) ausgeführt wird, ist die Ausgabe wie folgt.

19/11/2016 12:18:37 AM: Task 1 started
19/11/2016 12:18:37 AM: Task 3 started
19/11/2016 12:18:37 AM: Task 2 started
Caught Exception in Main at 19/11/2016 12:18:40 AM: Task 1 throwing at 19/11/2016 12:18:38 AM
Done.

Wenn das folgende Programm mit Task.WaitAll(taskArray) ausgeführt wird, ist die Ausgabe wie folgt.

19/11/2016 12:19:29 AM: Task 1 started
19/11/2016 12:19:29 AM: Task 2 started
19/11/2016 12:19:29 AM: Task 3 started
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 1 throwing at 19/11/2016 12:19:30 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 2 throwing at 19/11/2016 12:19:31 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 3 throwing at 19/11/2016 12:19:32 AM
Done.

Das Programm:

class MyAmazingProgram
{
    public class CustomException : Exception
    {
        public CustomException(String message) : base(message)
        { }
    }

    static void WaitAndThrow(int id, int waitInMs)
    {
        Console.WriteLine($"{DateTime.UtcNow}: Task {id} started");

        Thread.Sleep(waitInMs);
        throw new CustomException($"Task {id} throwing at {DateTime.UtcNow}");
    }

    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            await MyAmazingMethodAsync();
        }).Wait();

    }

    static async Task MyAmazingMethodAsync()
    {
        try
        {
            Task[] taskArray = { Task.Factory.StartNew(() => WaitAndThrow(1, 1000)),
                                 Task.Factory.StartNew(() => WaitAndThrow(2, 2000)),
                                 Task.Factory.StartNew(() => WaitAndThrow(3, 3000)) };

            Task.WaitAll(taskArray);
            //await Task.WhenAll(taskArray);
            Console.WriteLine("This isn't going to happen");
        }
        catch (AggregateException ex)
        {
            foreach (var inner in ex.InnerExceptions)
            {
                Console.WriteLine($"Caught AggregateException in Main at {DateTime.UtcNow}: " + inner.Message);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught Exception in Main at {DateTime.UtcNow}: " + ex.Message);
        }
        Console.WriteLine("Done.");
        Console.ReadLine();
    }
}
42
tymtam

Ein Beispiel für den Unterschied: Wenn Sie eine Aufgabe haben, die etwas mit dem UI-Thread zu tun hat (z. B. eine Aufgabe, die eine Animation in einem Storyboard darstellt), wenn Sie Task.WaitAll(), dann ist der UI-Thread blockiert und die UI wird nie aktualisiert. Wenn Sie await Task.WhenAll() verwenden, wird der UI-Thread nicht blockiert und die UI wird aktualisiert.

17
J. Long

Was machen Sie:

  • Intern machen beide dasselbe.

Was ist der Unterschied:

  • WaitAll ist ein blockierender Anruf
  • WhenAll - not - code wird weiterhin ausgeführt

Verwenden Sie welche, wenn:

  • WaitAll Wann kann ich nicht fortfahren, ohne das Ergebnis zu haben?
  • WhenAll wann wird was nur benachrichtigt, nicht geblockt
4
i100