Асинхронность (async await) в C#

Асинхронность в C# используется для выполнения операций, не блокируя основной поток выполнения. Это особенно важно при работе с вводом-выводом (I/O), запросами к базе данных и сетевыми вызовами, где задержки могут негативно сказаться на производительности.

Основные принципы асинхронного программирования

C# поддерживает асинхронное программирование с использованием ключевых слов async и await, а также типов Task и Task<T>. Они позволяют писать код, который выполняется асинхронно без явного управления потоками.

public async Task<string> GetDataAsync()
{
    using var httpClient = new HttpClient();
    
    return await httpClient.GetStringAsync("https://example.com");
}

Разница между синхронным и асинхронным кодом

Синхронный код

При выполнении синхронного кода поток блокируется до завершения операции.

public string GetData()
{
    using var httpClient = new HttpClient();
    
    return httpClient.GetStringAsync("https://example.com").Result;
}

Этот код заблокирует вызывающий поток, пока не получит ответ от сервера.

Асинхронный код

Асинхронный код позволяет освободить поток, пока выполняется операция.

public async Task<string> GetDataAsync()
{
    using var httpClient = new HttpClient();
    return await httpClient.GetStringAsync("https://example.com");
}

Здесь выполнение метода приостанавливается на await, но основной поток может продолжить работу.

Использование async и await

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

public async Task<int> ProcessDataAsync()
{
    await Task.Delay(2000); // Имитация задержки
    return 1;
}

Обработка исключений в асинхронном коде

Асинхронные методы могут выбрасывать исключения, которые можно обработать с помощью try-catch.

public async Task<string> GetDataSafelyAsync()
{
    try
    {
        using var httpClient = new HttpClient();
        return await httpClient.GetStringAsync("https://example.com");
    }
    catch (Exception ex)
    {
        return $"Ошибка: {ex.Message}";
    }
}

Асинхронные коллекции (IAsyncEnumerable<T>)

Для работы с потоковыми данными в C# можно использовать IAsyncEnumerable<T> и await foreach.

public async IAsyncEnumerable<int> GenerateNumbersAsync()
{
    for (int i = 0; i < 5; i++)
    {
        await Task.Delay(1000);
        yield return i;
    }
}

public async Task ProcessNumbersAsync()
{
    await foreach (var number in GenerateNumbersAsync())
    {
        Console.WriteLine(number);
    }
}

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