День двести четырнадцатый. #ЗаметкиНаПолях
Многопоточность.
9. Async/await. Продолжение
Выражения await
Синтаксис выражения
На выражения
1. Во-первых, выражения должны быть «ожидаемыми» (awaitable), то есть реализовывать паттерн awaitable (о нём далее).
2. Их можно использовать только в асинхронных методах и асинхронных анонимных функциях. Даже внутри асинхронного метода нельзя использовать оператор
3. Оператор
4. Запрещено использовать
Дело в том, что монитор, используемый оператором
5. Всегда было возможно использовать
-
Продолжение следует…
Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.
Многопоточность.
9. Async/await. Продолжение
Выражения await
Синтаксис выражения
await
прост: за оператором await
следует другое выражение, которое возвращает значение. Вы можете ожидать результата вызова метода, переменной или свойства. Также выражение не обязано быть простым: можно объединить вызовы методов и дождаться результата:int result = await foo.Bar().Baz();Приоритет оператора
await
ниже, чем у точки, поэтому этот код эквивалентен следующему:int result = await (foo.Bar().Baz());Ограничения выражений await
На выражения
await
накладываются некоторые ограничения.1. Во-первых, выражения должны быть «ожидаемыми» (awaitable), то есть реализовывать паттерн awaitable (о нём далее).
2. Их можно использовать только в асинхронных методах и асинхронных анонимных функциях. Даже внутри асинхронного метода нельзя использовать оператор
await
в анонимной функции, если она не обозначена как асинхронная.3. Оператор
await
запрещён в небезопасном контексте. Это не означает, что вы не можете использовать небезопасный код в асинхронном методе; вы просто не можете использовать оператор await
в этой части.4. Запрещено использовать
await
внутри блокировки (lock
). Если вам когда-нибудь потребуется блокировка ресурса на время выполнения асинхронной операции, вам следует изменить код. Не пытайтесь обойти ограничения компилятора, вызывая Monitor.TryEnter
и Monitor.Exit
вручную с помощью блока try
/finally
. Если это жизненно необходимо сделать, попробуйте использовать SemaphoreSlim
с его метод WaitAsync
.Дело в том, что монитор, используемый оператором
lock
, может быть освобождён только тем же потоком, который первоначально его получил, в то время, как весьма вероятно, что поток, выполняющий код перед выражением await
, будет отличаться от потока, выполняющего код после него. Либо во время ожидания первоначальный поток будет использован для выполнения какого-либо другого кода. По сути, оператор lock
и асинхронность несовместимы.5. Всегда было возможно использовать
await
в блоке try
, который имеет только блок finally
, а, следовательно, и в операторе using
. Но до C#6 нельзя было использовать await
в следующих блоках:-
try
с блоком catch
- catch
- finally
Начиная с C#6 эти ограничения сняты.Продолжение следует…
Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 5.