Запустив программу, вы увидите, что три задачи запускаются в порядке от наименьшего значения, указанного при вызове метода
Sleep
:
Fun With Async ===>
Done with work!
Void method completed
Done with second task!
Done with third task!
Done with first task!
Completed
Существует
также метод
WhenAnу
, возвращающий задачу, которая завершилась. Для демонстрации работы
WhenAny
измените последнюю строку метода
MultipleAwaits
следующим образом:
await Task.WhenAny(task1, task2, task3);
В результате вывод становится таким:
Fun With Async ===>
Done with work!
Void method completed
Done with second task!
Completed
Done with third task!
Done with first task!
Вызов асинхронных методов из неасинхронных методов
В каждом из предшествующих примеров ключевое слово
async
использовалось для возвращения в поток вызывающего кода, пока выполняется асинхронный метод. В целом ключевое слово
await
может применяться только в методе, помеченном как
async
. А что если вы не можете (или не хотите) помечать метод с помощью
async
?
К счастью, существуют другие способы вызова асинхронных методов. Если вы просто не используете ключевое слово
await
, тогда код продолжает работу после асинхронного метода, не возвращая управление вызывающему коду. Если вам необходимо ожидать завершения асинхронного метода (что происходит, когда применяется ключевое слово
await
), то существуют два подхода.
Первый подход предусматривает просто использование свойства
Result
с методами, возвращающими
Task<T>
, или метода
Wait
с методами, возвращающими
Task/Task<T>
. (Вспомните, что метод, который возвращает значение, обязан возвращать
Task<T>
, будучи асинхронным, а метод, не имеющий возвращаемого значения, возвращает
Task
, когда является асинхронным.) Если метод терпит неудачу, то возвращается
AggregateException
.
Можете также добавить вызов
GetAwaiter.GetResult
, который обеспечивает такой же эффект, как ключевое слово
await
в асинхронном методе, и распространяет исключения в той же манере, что и
async/await
. Тем не менее, указанные методы помечены в документации как "не предназначенные для внешнего использования", а это значит, что они могут измениться либо вовсе исчезнуть в какой-то момент в будущем. Вызов
GetAwaiter.GetResult
работает как с методами, возвращающими значение, так и с методами без возвращаемого
значения.
На заметку! Решение использовать свойство
Result
или вызов
GetAwaiter.GetResult
с
Task<T>
возлагается полностью на вас, и большинство разработчиков принимают решение, основываясь на обработке исключений. Если ваш метод возвращает