Использование await
не ждет, вот и весь смысл. Если вы хотите подождать, вы используете Task.Wait
.
Однако выполнение метода async
возобновится только после завершения ожидаемой задачи (это продолжение). Давайте посмотрим на ваш метод async
:
private static async Task Run(Action action)
{
await Task.Run(action);
// There is nothing here
}
Нет кода для выполнения после выполнения задачи ... Хорошо, метод async
возвращает задачу, которая завершается, когда она выполнена. Давайте посмотрим, если вы await
это ...
Run(() => LongProcess()).ContinueWith( t => Run(() => LongerProcess()));
Вы этого не сделаете. Вы запускаете эту задачу и забываете о ней.
Я думаю, что это то, что вы хотите:
static async void Main(string[] args)
{
await Run(() => LongProcess());
await Run(() => LongerProcess());
int count = 5;
do
{
Console.WriteLine(count.ToString());
Thread.Sleep(100);
count++;
} while (count < 20);
Console.ReadKey();
}
Примечание : Asyn c Main is a C# 7.1 функция.
Этот код будет запускать задачу, которая вызывает LongProcess
, а затем в качестве продолжения задачу, которая запускает LongerProcess
, а затем в качестве продолжения остальной код.
Почему вы хотите, чтобы вместо простого синхронного вызова этих методов я был вне себя.
Кстати, в методе async
вы можете использовать await Task.Delay(milliseconds)
вместо Thread.Sleep(milliseconds)
. Преимущество в том, что поток не ждет. Это похоже на создание продолжения для одного таймера выполнения.
Если async/await
- это просто продолжения, вам может быть интересно, почему люди захотят использовать их вместо ContinueWith
.
Позвольте привести несколько причин:
- Код с
async/await
легче читать. Менее вложенные вещи, омрачающие код. Вы можете понять, что делает код, независимо от понимания многопоточности. - Код с
async/await
легче писать. Вы просто пишете это так, как если бы все было синхронно с некоторыми async
и await
, искрившимися там. Вы можете написать синхронный код и потом беспокоиться о том, как сделать его параллельным. Вы также в конечном итоге пишете меньше, что означает, что вы более продуктивны. - Код с
async/await
умнее ™. Компилятор переписывает ваш код как конечный автомат, позволяя вам помещать await
внутри операторов без какого-либо кода гимнастики ™. И это распространяется на обработку исключений. Видите ли, в вашем огне и забыли продолжение задачи, вы не обрабатываете исключения. Что делать, если LongerProcess
бросает? Что ж, с async/await
вы можете просто поместить await
внутрь try ... catch
, и он делает правильные вещи ™.
Это все хорошее разделение интересов.
Вы можете также задаться вопросом, в какой ситуации лучше использовать async/await
вместо синхронного кода. И ответ заключается в том, что он сияет при работе с операциями ввода-вывода. При взаимодействии с внешней системой обычно не сразу получить ответ. Например, если вы хотите читать с диска или загружать из сети.
Фактически, если вы рассматриваете манипулирование формой и обработку ее события как операции ввода-вывода (потому что они есть). Вы увидите, что они являются хорошим местом для использования async/await
. В частности, учитывая, что контекст синхронизации для потоков пользовательского интерфейса будет сохранять продолжения в том же потоке по умолчанию. Конечно, вы можете использовать async/await
с операциями с привязкой к процессору, используя Task.Run
. Когда это хорошая идея? Ах, да, когда вы хотите, чтобы интерфейс реагировал.