Quelle est la différence entre Task.WaitAll()
et Task.WhenAll()
depuis le CTP Async? Pouvez-vous fournir un exemple de code pour illustrer les différents cas d'utilisation?
Quelle est la différence entre Task.WaitAll()
et Task.WhenAll()
depuis le CTP Async? Pouvez-vous fournir un exemple de code pour illustrer les différents cas d'utilisation?
Réponses:
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 qu'à partir d'une méthode asynchrone, vous pouvez utiliser:
await Task.WhenAll(tasks);
... ce qui signifie que votre méthode continuera une fois que tout sera terminé, mais vous ne lierez pas un fil de discussion jusqu'à ce moment-là.
WhenAll
, mais ce n'est pas la même chose que de bloquer le thread.
Alors que la réponse de JonSkeet explique la différence d'une manière généralement excellente, il existe une autre différence: la gestion des exceptions .
Task.WaitAll
jette un AggregateException
lorsque l'une des tâches est lancée et vous pouvez examiner toutes les exceptions levées. Le await
in await Task.WhenAll
déballe le AggregateException
et ne 'retourne' que 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();
}
}
await t1; await t2; await t3;
vsawait Task.WhenAll(t1,t2,t3);
await
, pas une différence entre les deux méthodes. Les deux propagent un AggregateException
, en lançant directement ou via une propriété (la Task.Exception
propriété).
Comme exemple de différence - si vous avez une tâche, elle fait quelque chose avec le thread d'interface utilisateur (par exemple, une tâche qui représente une animation dans un Storyboard) si vous Task.WaitAll()
le thread d'interface utilisateur est alors bloqué et l'interface utilisateur n'est jamais mise à 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:
À utiliser lorsque:
WaitAll
que je comprends.
Task.WaitAll
avoir fait votre autre travail? Je veux dire, au lieu de l'appeler juste après avoir commencé vos tâches.