Quelle est la différence entre Task.WaitAll()
et Task.WhenAll()
du CTP Async? Pouvez-vous fournir un exemple de code pour illustrer les différents cas d'utilisation?
Task.WaitAll
bloque le thread actuel jusqu'à ce que tout soit terminé.
Task.WhenAll
renvoie une tâche qui représente l'action d'attendre que tout soit terminé.
Cela signifie que depuis une méthode asynchrone, vous pouvez utiliser:
await Task.WhenAll(tasks);
... ce qui signifie que votre méthode continuera quand tout sera terminé, mais vous ne ferez rien pour que traîner jusqu'à ce que ça dure.
Alors que la réponse de JonSkeet explique la différence de manière généralement excellente, la plus grande différence pratique est traitement des exceptions. EDIT: D'accord - ce n'est pas la plus grande différence pratique, c'est une différence.
Task.WaitAll
lève un AggregateException
lorsqu'une tâche est lancée et vous pouvez examiner toutes les exceptions renvoyées. La await
dans await Task.WhenAll
décompresse la AggregateException
et 'renvoie' uniquement la première exception.
Lorsque le programme ci-dessous s'exécute avec await Task.WhenAll(taskArray)
, la sortie 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.
Lorsque le programme ci-dessous est exécuté avec Task.WaitAll(taskArray)
, la sortie est la suivante.
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();
}
}
À titre d’exemple, si vous avez une tâche, le thread de l’interface utilisateur exécute une action (par exemple, une tâche représentant une animation dans un storyboard) si vous Task.WaitAll()
, le thread d’interface utilisateur est bloqué et l’interface utilisateur ne s'affiche jamais. mis à jour. Si vous utilisez await Task.WhenAll()
, le thread d'interface utilisateur n'est pas bloqué et l'interface utilisateur sera mise à jour.
Que font-ils:
Quelle est la différence:
Utilisez lequel quand: