Запуск нескольких задач async и ожидание их завершения

Мне нужно запустить несколько задач async в консольном приложении и дождаться их завершения до дальнейшей обработки.

Там много статей, но я, кажется, больше смущен, чем больше читаю. Я читал и понимал основные принципы библиотеки задач, но я явно пропускаю ссылку где-то.

Я понимаю, что можно объединить задачи так, чтобы они запускались после того, как они завершались (что в значительной степени является сценарием для всех прочитанных статей), но я хочу, чтобы все мои задачи выполнялись одновременно, и я хочу знать один раз они все закончены.

Какова самая простая реализация для такого сценария?

В обоих ответах не упоминается ожидаемая Task.WhenAll После Task.WhenAll :

 var task1 = DoWorkAsync(); var task2 = DoMoreWorkAsync(); await Task.WhenAll(task1, task2); 

Основное различие между Task.WaitAll и Task.WhenAll заключается в том, что первый будет блокировать (подобно использованию Wait в одной задаче), в то время как последний не будет и может быть ожидаем, возвращая управление вызывающему абоненту до тех пор, пока все задачи не закончатся.

Более того, обработка исключений отличается:

Task.WaitAll :

По крайней мере один из экземпляров Task был отменен – ​​или – исключение было отправлено во время выполнения хотя бы одного из экземпляров Task. Если задача была отменена, в своде InnerExceptions в агрегированном исключении содержится исключение OperationCanceledException.

Task.WhenAll :

Если какая-либо из поставленных задач завершена в неисправном состоянии, возвращенная задача также будет завершена в состоянии Faulted, где ее исключения будут содержать агрегацию набора исключенных исключений из каждой из поставленных задач.

Если ни одна из поставленных задач не сработала, но хотя бы одна из них была отменена, возвращаемая задача завершится в состоянии «Отменено».

Если ни одна из задач не была выполнена, и ни одна из задач не была отменена, итоговая задача завершится в состоянии RanToCompletion. Если предоставленный массив / перечисляемый не содержит задач, возвращаемая задача немедленно перейдет в состояние RanToCompletion до того, как будет возвращена вызывающему.

Вы могли бы создать много задач, таких как:

 List TaskList = new List(); foreach(...) { var LastTask = new Task(SomeFunction); LastTask.Start(); TaskList.Add(LastTask); } Task.WaitAll(TaskList.ToArray()); 

Лучший вариант, который я видел, – это следующий метод расширения:

 public static Task ForEachAsync(this IEnumerable sequence, Func action) { return Task.WhenAll(sequence.Select(action)); } 

Назовите это так:

 await sequence.ForEachAsync(item => item.SomethingAsync(blah)); 

Или с асинхронной лямбдой:

 await sequence.ForEachAsync(async item => { var more = await GetMoreAsync(item); await more.FrobbleAsync(); }); 

Вы хотите связать Task s, или они могут быть вызваны параллельно?

Для цепочки
Просто сделай что-нибудь вроде

 Task.Run(...).ContinueWith(...).ContinueWith(...).ContinueWith(...); Task.Factory.StartNew(...).ContinueWith(...).ContinueWith(...).ContinueWith(...); 

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

Параллельно
Самый простой метод, с которым я столкнулся: Parallel.Invoke В противном случае есть Task.WaitAll или вы даже можете использовать WaitHandle s для обратного отсчета до нулевых действий слева (подождите, есть новый class: CountdownEvent ) или …

Вы можете использовать WhenAll который вернет ожидаемую Task или WaitAll которой нет типа возврата, и блокирует дальнейшее выполнение кода, Thread.Sleep с Thread.Sleep пока все задачи не будут завершены, отменены или не будут устранены.

введите описание изображения здесь

пример

 var tasks = new Task[] { await TaskOperationOne(), await TaskOperationTwo() }; Task.WaitAll(tasks); // or await Task.WhenAll(tasks); 

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

Вот как я делаю это с помощью массива Func <> :

 var tasks = new Func[] { () => myAsyncWork1(), () => myAsyncWork2(), () => myAsyncWork3() }; await Task.WhenAll(tasks.Select(task => task()).ToArray()); //Async Task.WaitAll(tasks.Select(task => task()).ToArray()); //Or use WaitAll for Sync 
  • Запуск задач в foreach Loop использует значение последнего элемента
  • Должны ли мы переключиться на использование асинхронного ввода-вывода по умолчанию?
  • Выполнение задач параллельно
  • В чем разница между возвратом пустоты и возвратом задачи?
  • Вызов синхронного асинхронного метода
  • WaitAll vs WhenAll
  • Очередь процесса с многопоточным или задачами
  • Interesting Posts

    Win7: инвертировать цвета одного конкретного окна

    Как использовать пользовательские разрешения в Android?

    Как создать дочерние компоненты из css-файла родительского компонента?

    Могу ли я безопасно игнорировать предупреждение тестирования логотипа Windows при установке VirtualBox в Windows XP?

    Удаление пробела в множителе gnuplot

    Моделирование базы данных полиморфных ассоциаций – сначала против первого кода

    разница и когда использовать getApplication (), getApplicationContext (), getBaseContext () и someClass.this

    Как вы присоединяетесь к одной таблице дважды в mysql?

    Mathematica: Растр в 3D-графике

    Как записать макросы для Autohotkey?

    Рабочая станция VMware: как уменьшить максимальный размер .vmdk

    Тестовые этикетки для регрессионного кофе, поплавок не допускаются?

    Как получить пространства имен в файлах XML с помощью Xpath

    Проблема с IOS7 (только) stdlibc ++

    CSS: установка ширины / высоты в процентах минус пиксели

    Давайте будем гением компьютера.