4 ответов:
Task.WaitAllблокирует текущий поток, пока все не завершено.
Task.WhenAllвозвращает a задание который представляет собой действие ожидания, пока все не будет завершено.это означает, что из async-метода, вы можете использовать:
await Task.WhenAll(tasks);... это означает, что ваш метод будет продолжаться, когда все будет завершено, но вы не будете связывать нить, чтобы просто болтаться до этого времени.
в то время как ответ Джонскита объясняет разницу, как правило, отличным способом для меня самая большая практическая разница обработка исключений.
Task.WaitAllвыдаетAggregateExceptionкогда любая из задач бросает, и вы можете изучить все брошенные исключения. Элементawaitнаawait Task.WhenAllразворачивает и только первое исключение.когда программа выполняет с
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(); } }
в качестве примера разницы -- если у вас есть задача делает что-то с потоком пользовательского интерфейса (например, задача, которая представляет анимацию в раскадровке), если вы
Task.WaitAll()затем поток пользовательского интерфейса блокируется, и пользовательский интерфейс никогда не обновляется. если вы используетеawait Task.WhenAll()тогда поток пользовательского интерфейса не блокируется, и пользовательский интерфейс будет обновлен.
что они делают:
- внутренне оба делают то же самое.
какая разница:
- WaitAll - это блокирующий вызов
- WhenAll - не-код будет продолжать выполнение
использование когда:
- WaitAll когда не может продолжаться без результата
- WhenAll когда что просто быть уведомленным, а не заблокированным
Comments