Какие исключения нельзя остановить в блоке catch?csharp-69

Как работают асинхронные методы

Основные концепции асинхронности в C#

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

public async Task<string> GetDataAsync()
{
    // 1. Метод начинает выполнение в вызывающем потоке
    var data = await httpClient.GetStringAsync("https://api.example.com/data");

    // 3. Продолжение выполняется после завершения операции
    return data.ToUpper();
}

Механизм работы async/await

  1. Вызов метода:

    • При вызове асинхронного метода создается state-машина
    • Выполнение идет синхронно до первого await
  2. Ожидание операции:

    • При встрече await поток освобождается (если операция не завершена)
    • Управление возвращается вызывающему коду
  3. Продолжение (continuation):

    • После завершения операции выполнение возобновляется
    • Контекст синхронизации сохраняется (если не отключено явно)

Под капотом компилятора

Компилятор преобразует асинхронный метод в сложную структуру:

// Примерное представление сгенерированного кода
[AsyncStateMachine(typeof(GetDataAsyncStateMachine))]
public Task<string> GetDataAsync()
{
    var stateMachine = new GetDataAsyncStateMachine();
    stateMachine._this = this;
    stateMachine._builder = AsyncTaskMethodBuilder<string>.Create();
    stateMachine._state = -1;
    stateMachine._builder.Start(ref stateMachine);
    return stateMachine._builder.Task;
}

Отличие асинхронности от параллелизма

Асинхронность

Характеристики:

  • Цель: Эффективное использование потоков (особенно при I/O)
  • Потоки: Может использовать один поток
  • Модель: Освобождение потока во время ожидания
  • Использование: async/await, Task, ValueTask

Пример:

public async Task ProcessDataAsync()
{
    var data1 = await LoadData1Async(); // Освобождает поток во время загрузки
    var data2 = await LoadData2Async(); // Освобождает поток во время загрузки
    // ...
}

Параллелизм

Характеристики:

  • Цель: Выполнение нескольких операций одновременно
  • Потоки: Использует несколько потоков
  • Модель: Физическое одновременное выполнение
  • Использование: Parallel.For, Task.Run, PLINQ

Пример:

public void ProcessDataInParallel()
{
    Parallel.For(0, 100, i =>
    {
        Compute(i); // Выполняется одновременно в нескольких потоках
    });
}

Ключевые различия

АспектАсинхронностьПараллелизм
ЦельЭффективность использования потоковУвеличение производительности
ПотокиМожет использовать 1 потокТребует несколько потоков
БлокировкаНе блокирует потокиМожет блокировать потоки
Идеально дляI/O операцийCPU-bound операций
РесурсыЭкономит потокиПотребляет дополнительные потоки

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

Асинхронность лучше:

  • Веб-запросы
  • Работа с файлами/БД
  • Сетевые операции
  • Ожидание внешних сервисов
public async Task<string> DownloadPageAsync(string url)
{
    using var client = new HttpClient();
    return await client.GetStringAsync(url);
}

Параллелизм лучше:

  • Обработка больших данных
  • Математические вычисления
  • Обработка изображений
  • Анализ данных
public void ProcessImages(Image[] images)
{
    Parallel.ForEach(images, image =>
    {
        image.ApplyFilters();
    });
}

Комбинирование подходов

public async Task ProcessAllDataAsync()
{
    // Асинхронная загрузка данных
    var data = await LoadDataAsync();

    // Параллельная обработка
    await Task.Run(() =>
    {
        Parallel.ForEach(data, item =>
        {
            ProcessItem(item);
        });
    });

    // Асинхронное сохранение
    await SaveResultsAsync();
}

Важные нюансы

  1. Async void: Использовать только для обработчиков событий
  2. ConfigureAwait(false): Для библиотечного кода без контекста синхронизации
  3. Task.Run: Не использовать просто для "асинхронности" в веб-приложениях
  4. Deadlocks: Возможны при неправильном смешивании sync/async кода

Резюмируем:

асинхронность и параллелизм - это разные концепции для разных задач. Асинхронность позволяет эффективно использовать потоки при операциях ожидания, тогда как параллелизм увеличивает производительность за счет одновременного выполнения кода на нескольких ядрах процессора. Грамотное сочетание этих подходов позволяет создавать высокопроизводительные и отзывчивые приложения.