TG Telegram Group & Channel
.NET Разработчик | United States America (US)
Create: Update:

День 1030. #ЗаметкиНаПолях #AsyncTips
Потребление асинхронных потоков
Создание асинхронных потоков

Задача: обработать результаты асинхронного потока.

Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в await foreach. Например, для асинхронного потока, который потребляет ответы API по страницам, можно организовать вывод элементов в консоль:

public async Task ProcessAsync(HttpClient client)
{
await foreach (var value in GetAsync(client))
{
Console.WriteLine(value);
}
}

На концептуальном уровне вызывается метод GetAsync, который возвращает IAsyncEnumerable<T>. Цикл foreach затем создаёт асинхронный перечислитель на базе асинхронного потока. Асинхронные перечислители на логическом уровне похожи на обычные перечислители, не считая того, что операция «получить следующий элемент» может быть асинхронной. Таким образом, await foreach будет ожидать поступления следующего элемента или завершения асинхронного перечислителя. Если элемент поступил, то await foreach выполнит тело цикла; если асинхронный перечислитель завершён, происходит выход из цикла.

Также можно выполнить асинхронную обработку каждого элемента:
await foreach (var val in GetAsync(client))
{
// асинхронная работа
await Task.Delay(100);
Console.WriteLine(val);
}

В этом случае await foreach не переходит к следующему элементу до завершения тела цикла. Таким образом, await foreach асинхронно получит первый элемент, после чего асинхронно выполнит тело цикла для первого элемента, затем асинхронно получит второй элемент, асинхронно выполнит тело цикла для второго элемента и т.д.

В await foreach скрыта команда await: к операции «получить следующий элемент» применяется await. С обычной командой await можно обойти захват контекста с помощью ConfigureAwait(false). Асинхронные потоки также это поддерживают:
await foreach (var val in
GetValuesAsync(client).ConfigureAwait(false))
{
await Task.Delay(100)
.ConfigureAwait(false);
Console.WriteLine(val);
}

Итого
await foreach — самый логичный способ потребления асинхронных потоков. Язык поддерживает ConfigureAwait(false) для предотвращения захвата контекста в await foreach. Также возможен вариант с передачей маркеров отмены. Об этом позже.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.

День 1030. #ЗаметкиНаПолях #AsyncTips
Потребление асинхронных потоков
Создание асинхронных потоков

Задача: обработать результаты асинхронного потока.

Решение
Потребление асинхронного потока основано на объединении конструкций ожидания и перечисления в await foreach. Например, для асинхронного потока, который потребляет ответы API по страницам, можно организовать вывод элементов в консоль:
public async Task ProcessAsync(HttpClient client)
{
await foreach (var value in GetAsync(client))
{
Console.WriteLine(value);
}
}

На концептуальном уровне вызывается метод GetAsync, который возвращает IAsyncEnumerable<T>. Цикл foreach затем создаёт асинхронный перечислитель на базе асинхронного потока. Асинхронные перечислители на логическом уровне похожи на обычные перечислители, не считая того, что операция «получить следующий элемент» может быть асинхронной. Таким образом, await foreach будет ожидать поступления следующего элемента или завершения асинхронного перечислителя. Если элемент поступил, то await foreach выполнит тело цикла; если асинхронный перечислитель завершён, происходит выход из цикла.

Также можно выполнить асинхронную обработку каждого элемента:
await foreach (var val in GetAsync(client))
{
// асинхронная работа
await Task.Delay(100);
Console.WriteLine(val);
}

В этом случае await foreach не переходит к следующему элементу до завершения тела цикла. Таким образом, await foreach асинхронно получит первый элемент, после чего асинхронно выполнит тело цикла для первого элемента, затем асинхронно получит второй элемент, асинхронно выполнит тело цикла для второго элемента и т.д.

В await foreach скрыта команда await: к операции «получить следующий элемент» применяется await. С обычной командой await можно обойти захват контекста с помощью ConfigureAwait(false). Асинхронные потоки также это поддерживают:
await foreach (var val in
GetValuesAsync(client).ConfigureAwait(false))
{
await Task.Delay(100)
.ConfigureAwait(false);
Console.WriteLine(val);
}

Итого
await foreach — самый логичный способ потребления асинхронных потоков. Язык поддерживает ConfigureAwait(false) для предотвращения захвата контекста в await foreach. Также возможен вариант с передачей маркеров отмены. Об этом позже.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 3.


>>Click here to continue<<

.NET Разработчик




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)