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 ?
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.
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();
}
}
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.
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é