Я несколько раз утверждал свое понимание async/await, часто с некоторыми дебатами относительно того, насколько я прав. Я был бы очень признателен, если бы кто-нибудь мог подтвердить или опровергнуть мое понимание и прояснить любые заблуждения, чтобы я не распространял дезинформацию.
Высокоуровневое понимание
async
/await
- это способ избежать обратного вызова ада при написании асинхронного кода. Нить, выполняющая асинхронный метод, вернется в пул потоков, когда встретится с await
, и выполнит выполнение после завершения ожидаемой операции.
Низкоуровневое понимание
JIT разделит асинхронные методы на отдельные части вокруг точек await
, что позволит повторно войти в метод с сохранением состояния метода. Под обложками подразумевается какая-то государственная машина.
Отношение к Concurrency
async
/await
не подразумевает какой-либо concurrency. Приложение, написанное с использованием async
/await
, может быть полностью однопоточным, при этом все еще пожиная все преимущества, так же как и node.js, хотя и с обратными вызовами. В отличие от node.js,.NET многопоточен, поэтому, имея async
/await
, вы получаете преимущества неблокирующего ввода-вывода без использования обратных вызовов, а также с несколькими потоками выполнения.
Преимущества
async
/await
освобождает потоки, чтобы делать другие вещи, ожидая завершения ввода-вывода. Его также можно использовать в сочетании с TPL для работы с ЦП, связанной с несколькими потоками, или от потока пользовательского интерфейса.
Чтобы извлечь выгоду из неблокирующего IO, асинхронные методы должны быть построены поверх API, которые фактически используют неблокирующий IO, которые в конечном итоге предоставляются ОС.
Неправильное использование
Это самая большая точка зрения в моем понимании. Многие считают, что перенос операции блокировки в Task
и использование async
/await
приведет к увеличению производительности. Создав дополнительный поток для обработки операции, возвращая исходный поток в пул потоков, а затем возобновляя исходный метод после завершения задачи, все, что происходит, являются ненужными переключателями контекста, хотя и не освобождает потоки для выполнения другой работы. Хотя это не столько злоупотребление async
/await
, сколько и TPL, это мышление, похоже, связано с непониманием async
/await
.