Асинхронность в 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 значительно упрощает работу с асинхронными операциями по сравнению с традиционными подходами на основе потоков.