WaitAll vs WhenAll

Quelle est la différence entre Task.WaitAll() et Task.WhenAll() du CTP Async ? Pouvez-vous donner un exemple de code pour illustrer les différents cas d'utilisation ?

239
demandé sur Alberto Solano 2011-05-25 15:01:16

4 réponses

Task.WaitAll bloque le fil courant jusqu'à ce que tout soit terminé.

Task.WhenAll renvoie une tâche qui représente l'action d'attendre jusqu'à ce que tout soit terminé.

cela signifie que d'une méthode async, vous pouvez utiliser:

await Task.WhenAll(tasks);

... ce qui signifie que votre méthode continuera quand tout sera terminé, mais vous ne serez pas attacher un fil à traîner juste autour jusqu'à ce moment.

368
répondu Jon Skeet 2018-05-31 09:17:12

alors que la réponse de JonSkeet explique la différence d'une manière typiquement excellente pour moi, la plus grande différence pratique est exception handling .

Task.WaitAll lance un AggregateException lorsque l'une des tâches lance et vous pouvez examiner toutes les exceptions lancées. Le await dans await Task.WhenAll déballe le AggregateException et "retourne" seulement la première exception.

lorsque le programme ci-dessous s'exécute avec await Task.WhenAll(taskArray) la production est la suivante.

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.

quand le programme ci-dessous est exécuté avec Task.WaitAll(taskArray) la sortie est comme suit.

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.

Le programme:

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();
    }
}
29
répondu tymtam 2016-11-22 10:47:44

comme exemple de la différence -- si vous avez une tâche que fait quelque chose avec le thread UI (par exemple une tâche qui représente une animation dans un Storyboard) si vous Task.WaitAll() alors le thread UI est bloqué et L'UI n'est jamais mis à jour. si vous utilisez await Task.WhenAll() , alors le thread de L'interface utilisateur n'est pas bloqué, et l'interface utilisateur sera mise à jour.

13
répondu J. Long 2017-10-03 14:47:49

Que font-ils:

  • à l'interne, les deux font la même chose.

Quelle est la différence:

  • WaitAll est un appel de blocage
  • WhenAll - pas - code de poursuivre l'exécution de

à utiliser lorsque:

  • WaitAll quand ne peut pas continuer sans avoir le résultat
  • WhenAll quand ce qui vient d'être informé, pas bloqué
2
répondu i100 2018-08-23 13:54:38