Встречается на 38% собеседований по C#

Что такое асинхронность

Асинхронность — это подход к выполнению операций, при котором вызов метода не блокирует текущий поток, а позволяет ему продолжить выполнение других задач, пока операция выполняется в фоне. В C# асинхронность реализуется с помощью ключевых слов async и await, а также типов Task и Task<T>. Это позволяет писать код, который выглядит синхронно, но при этом не блокирует поток, что критично для отзывчивости UI и масштабируемости серверных приложений.

Как это работает

Асинхронный метод помечается ключевым словом async. Внутри такого метода обязательно должен быть хотя бы один оператор await. Когда выполнение доходит до await, метод приостанавливается и возвращает управление вызывающему коду, а поток освобождается для выполнения других задач. После завершения асинхронной операции выполнение метода продолжается с того места, где был await.

Важно понимать, что await не блокирует поток, а лишь приостанавливает выполнение текущего метода. Это достигается за счет того, что компилятор преобразует асинхронный метод в конечный автомат, который отслеживает состояние выполнения.

Пример

csharp
public async Task<string> GetDataAsync()
{
    using HttpClient client = new();
    // await приостанавливает выполнение, не блокируя поток
    string result = await client.GetStringAsync("https://api.example.com/data");
    return result;
}

В этом примере GetDataAsync возвращает Task<string>. При вызове await client.GetStringAsync(...) поток освобождается, а когда данные будут получены, выполнение метода продолжится, и результат будет возвращен.

Преимущества и подводные камни

Преимущества асинхронности:

  • Эффективное использование потоков: потоки не простаивают в ожидании завершения операций ввода-вывода.
  • Отзывчивость UI: интерфейс не зависает при выполнении длительных операций.
  • Масштабируемость серверных приложений: меньше потоков требуется для обработки большого количества запросов.

Подводные камни:

  • Deadlock: возникает, когда асинхронный метод вызывается синхронно (например, через .Result или .Wait()) в контексте с синхронизацией (например, UI-поток). Чтобы избежать, используйте ConfigureAwait(false) в библиотечном коде или не блокируйте поток при вызове асинхронных методов.
  • Исключения: в асинхронных методах исключения сохраняются в Task и выбрасываются при await. Обрабатывайте их с помощью try-catch вокруг await.
  • Неправильное использование async без await приводит к предупреждению компилятора и не дает преимуществ.

Когда использовать

Асинхронность следует использовать для операций ввода-вывода (сеть, файлы, базы данных) и длительных операций, которые не требуют интенсивного использования CPU. Для CPU-интенсивных задач лучше подходит Task.Run или параллельное программирование.

Коротко

  • Асинхронность позволяет не блокировать поток при выполнении операций.
  • В C# используется async/await и Task/Task<T>.
  • await приостанавливает метод, но не блокирует поток.
  • Избегайте deadlock'ов и правильно обрабатывайте исключения.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы