WaitAll vs WhenAll - PullRequest
       46

WaitAll vs WhenAll

285 голосов
/ 25 мая 2011

В чем разница между Task.WaitAll() и Task.WhenAll() от Async CTP? Можете ли вы предоставить пример кода для иллюстрации различных вариантов использования?

Ответы [ 4 ]

433 голосов
/ 25 мая 2011

Task.WaitAll блокирует текущий поток до тех пор, пока все не будет завершено.

Task.WhenAll возвращает задачу , которая представляет действие ожидания, пока все не будет завершено.Это означает, что из асинхронного метода вы можете использовать:

await Task.WhenAll(tasks);

... что означает, что ваш метод продолжит работу, когда все будет завершено, но вы не будете связывать поток, чтобы просто зависать до этого.

41 голосов
/ 19 ноября 2016

Хотя ответ 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();
    }
}
17 голосов
/ 13 апреля 2016

В качестве примера различия - если у вас есть задача, она делает что-то с потоком пользовательского интерфейса (например, задача, которая представляет анимацию в раскадровке), если вы Task.WaitAll(), тогда поток пользовательского интерфейса блокируется, а никогда не обновляется. если вы используете await Task.WhenAll(), тогда поток пользовательского интерфейса не блокируется, и пользовательский интерфейс будет обновлен.

4 голосов
/ 23 августа 2018

Что они делают:

  • Внутренне оба делают одно и то же.

Какая разница:

  • WaitAll является блокирующим вызовом
  • Когда все - нет - код продолжит выполнение

Используйте, когда:

  • WaitAll , когда невозможно продолжить без результата
  • КогдаВсе , когда о чем просто нужно уведомлять, а не блокировать
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...