День двести тринадцатый. #ЗаметкиНаПолях

Многопоточность.

9. Async/await. Продолжение

Определение асинхронных методов

Синтаксис для объявления асинхронного метода точно такой же, как и для любого другого метода, за исключением того, что он должен включать ключевое слово async в любом месте перед типом возврата:

public static async Task<int> FooAsync() { ... }

public async static Task<int> FooAsync() { ... }

async public Task<int> FooAsync() { ... }

public async virtual Task<int> FooAsync() { ... }



Тут есть небольшой секрет: разработчикам языка вообще не нужно было требовать включать слово async. Схожим образом компилятор интерпретирует yield return или yield break. Компилятор мог бы обнаруживать await внутри метода и использовать его для перехода в асинхронный режим. Но использование ключевого слова async значительно облегчает чтение кода. Оно сообщает вам, что этот метод асинхронный и в нём нужно искать выражение await.

Асинхронные функции ограничены следующими типами возврата:

- void

- Task

- Task<TResult>

- ValueTask<TResult> (C#7+ об этом типе позже)



Типы Task и Task<TResult> представляют операцию, которая может быть еще незавершена; Task<TResult> наследует от Task. Task<TResult> представляет операцию, которая возвращает значение типа TResult, а Task не возвращает результата. Однако лучше возвращать Task вместо void, поскольку Task позволяет вызывающему коду добавить собственные продолжения к возвращённой задаче, определять, выполнена ли задача и т.п. Возможность возврата void оставлена для совместимости с обработчиками событий (см. метод DisplayWebSiteLength в предыдущем посте). Подписка на события – это, пожалуй, единственный случай, когда рекомендуется возвращать void из асинхронного метода.

Хотя тип результата асинхронных методов довольно жестко ограничен, большинство других аспектов не отличаются от обычных методов: асинхронные методы могут быть обобщёнными, статическими или нестатическими и определять любые модификаторы доступа.

Однако существуют ограничения на параметры. Ни один из параметров асинхронного метода не может использовать модификаторы out или ref, т.к. они предназначены для возврата информации в вызывающий метод, что не имеет смысла при асинхронном вызове. Кроме того, не могут использоваться типы указателей.



Продолжение следует…



Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.