Что такое Async/Await
Async/Await — это синтаксическая конструкция в C#, которая позволяет писать асинхронный код, не блокируя поток выполнения. Она основана на классе Task и предоставляет удобный способ ожидания завершения длительных операций (например, обращений к базе данных, HTTP-запросам, работе с файлами) без блокировки текущего потока.
Как это работает
Ключевое слово async помечает метод как асинхронный. Однако само по себе оно не делает метод асинхронным — важно, что внутри такого метода используется await. Когда компилятор встречает await, он преобразует метод в конечный автомат: выполнение метода приостанавливается в точке await, а управление возвращается вызывающему коду. Поток, который выполнял метод, освобождается и может заниматься другими задачами. Когда ожидаемая операция завершается, выполнение метода возобновляется с того места, где было прервано.
Пример:
public async Task<string> GetDataAsync()
{
// Асинхронный вызов к внешнему ресурсу
string result = await httpClient.GetStringAsync("https://example.com");
// Выполнение продолжится после получения результата
return result;
}В этом примере await приостанавливает выполнение GetDataAsync, пока GetStringAsync не завершится. Поток, вызвавший этот метод, не блокируется и может обрабатывать другие события, например, обновлять интерфейс.
Подводные камни
asyncбезawait: если метод помеченasync, но не содержитawait, компилятор выдаст предупреждение. Такой метод выполняется синхронно, и его использование бессмысленно.- Блокировка в асинхронном методе: вызов синхронных методов (например,
.Resultили.Wait()) внутри асинхронного метода может привести к взаимоблокировке (deadlock), особенно в UI-приложениях с контекстом синхронизации. - Исключения: исключения, возникшие в асинхронном методе, сохраняются в
Taskи выбрасываются при ожидании черезawait. Если не ожидать задачу, исключение может быть потеряно. - Контекст синхронизации: в UI-приложениях
awaitпо умолчанию возвращает выполнение в исходный контекст (например, в поток UI). Это удобно, но может вызвать проблемы при длительных операциях, если не использоватьConfigureAwait(false).
Когда использовать
Async/Await следует применять для операций, которые реально выполняются асинхронно: ввод-вывод, сетевые запросы, работа с базами данных. Для CPU-интенсивных вычислений лучше использовать Task.Run или параллельные библиотеки, так как async не создаёт новый поток, а лишь освобождает текущий.
Коротко
asyncпомечает метод,await— точку приостановки ожидания.awaitне блокирует поток, а освобождает его для других задач.- Не используйте
asyncбезawait— это ошибка. - Избегайте синхронных блокировок внутри асинхронных методов.
- Применяйте для операций ввода-вывода, а не для CPU-интенсивных задач.
