В чем отличие Task.WaitAll()
и Task.WhenAll()
от асинхронной CTP? Можете ли вы предоставить пример кода для иллюстрации различных вариантов использования?
WaitAll vs WhenAll
Ответ 1
Task.WaitAll
блокирует текущий поток, пока все не будет завершено.
Task.WhenAll
возвращает задачу, которая представляет действие ожидания, пока все не будет завершено.
Это означает, что из асинхронного метода вы можете использовать:
await Task.WhenAll(tasks);
... что означает, что ваш метод продолжится, когда все будет завершено, но вы не будете связывать поток, чтобы просто торчать до этого времени.
Ответ 2
Хотя ответ JonSkeet объясняет разницу типично для меня, самое большое практическое отличие - обработка исключений. РЕДАКТИРОВАТЬ: Согласен - это не самая большая практическая разница, это разница.
Task.WaitAll
AggregateException
при возникновении любой из задач, и вы можете проверить все созданные исключения. await
в await Task.WhenAll
разворачивает AggregateException
и "возвращает" только первое исключение.
Когда приведенная ниже программа выполняется с await Task.WhenAll(taskArray)
вывод выглядит следующим образом.
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.
Когда приведенная ниже программа выполняется с помощью Task.WaitAll(taskArray)
вывод будет следующим.
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.
Программа:
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();
}
}
Ответ 3
В качестве примера разницы - если у вас есть задача, что-то делает с потоком пользовательского интерфейса (например, задача, представляющая анимацию в Storyboard), если вы Task.WaitAll()
, тогда поток пользовательского интерфейса блокируется и пользовательский интерфейс никогда не обновлялся. если вы используете await Task.WhenAll()
, тогда поток пользовательского интерфейса не будет заблокирован, и пользовательский интерфейс будет обновлен.
Ответ 4
Что они делают:
- Внутренне оба делают одно и то же.
Какая разница:
- WaitAll - это блокирующий вызов
- Когда все - не - код продолжит выполнение
Используйте, когда:
- WaitAll, когда невозможно продолжить без результата
- КогдаВсе когда то, что просто нужно уведомить, а не заблокировать