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

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

Задача: обработать асинхронный поток с использованием чётко определенных и хорошо протестированных операторов. Либо использовать LINQ, когда предикат является асинхронным, например, необходимо провести поиск каждого элемента в базе данных или API, чтобы узнать, должен ли он быть включен в итоговую последовательность.

Решение
Допустим, у нас есть метод, производящий асинхронную последовательность:

async IAsyncEnumerable<int> GetAsyncRange()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(100);
yield return i;
}
}

IAsyncEnumerable<T> включает поддержку LINQ в NuGet-пакете System.Linq.Async. Заметьте, что при этом в коде нужно использовать
using static System.Linq.AsyncEnumerable;

Операторы LINQ можно применять к асинхронным потокам. Доступны все знакомые операторы: Where, Select, SelectMany, Join и т.д. Результат представляет собой асинхронный поток:
IAsyncEnumerable<int> values =
GetAsyncRange().Where(value => value % 2 == 0);

await foreach (int result in values) {
Console.WriteLine(result);
}

Но что, если нам нужно передать в Where асинхронный предикат? Where их не поддерживает. Но есть подходящий оператор WhereAwait:
IAsyncEnumerable<int> values = 
GetAsyncRange().WhereAwait(
async value => {
// Асинхронная работа для определения,
// должен ли элемент быть включён в результат
await Task.Delay(10);
return value % 2 == 0;
});

Методы LINQ для асинхронных потоков можно использовать и для обычных перечисляемых объектов, вызвав ToAsyncEnumerable() для любого IEnumerable<T>. Результат можно использовать с WhereAwait, SelectAwait и другими операторами, принимающими асинхронные делегаты.

Операторы LINQ для асинхронных потоков могут оканчиваться суффиксами Async и Await. Операторы, заканчивающиеся суффиксом Async, возвращают обычное значение, допускающее ожидание. Операторы с суффиксом Await получают асинхронный делегат. Т.е. Await в имени подразумевает, что они используют await внутри переданного делегата.

Пример WhereAwait был приведёт выше.

Суффикс Async применяется только к операторам терминации (termination operators), которые извлекают некоторое значение или выполняют некоторые вычисления и возвращают асинхронное скалярное значение. Пример такого оператора — CountAsync, версия Count для асинхронного потока, которая может подсчитать количество элементов, соответствующих некоторому предикату:
int count = await GetAsyncRange()
.CountAsync(value => value % 2 == 0);

Предикат может также быть асинхронным. В этом случае используется метод CountAwaitAsync, поскольку он получает асинхронного делегата и производит одно терминальное значение:
int count = await GetAsyncRange().CountAwaitAsync(
async value => {
await Task.Delay(10);
return value % 2 == 0;
});

Итого
- Операторы без суффиксов (Where, Select) получают синхронные делегаты и выдают асинхронную последовательность.
- Операторы, которые получают асинхронные делегаты, имеют суффикс Await (WhereAwait, SelectAwait), и выдают асинхронную последовательность.
- Операторы, возвращающие терминальное значение, имеют суффикс Async (CountAsync), а также могут иметь суффикс Await, если получают асинхронный делегат (CountAwaitAsync).

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

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

Задача: обработать асинхронный поток с использованием чётко определенных и хорошо протестированных операторов. Либо использовать LINQ, когда предикат является асинхронным, например, необходимо провести поиск каждого элемента в базе данных или API, чтобы узнать, должен ли он быть включен в итоговую последовательность.

Решение
Допустим, у нас есть метод, производящий асинхронную последовательность:
async IAsyncEnumerable<int> GetAsyncRange()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(100);
yield return i;
}
}

IAsyncEnumerable<T> включает поддержку LINQ в NuGet-пакете System.Linq.Async. Заметьте, что при этом в коде нужно использовать
using static System.Linq.AsyncEnumerable;

Операторы LINQ можно применять к асинхронным потокам. Доступны все знакомые операторы: Where, Select, SelectMany, Join и т.д. Результат представляет собой асинхронный поток:
IAsyncEnumerable<int> values =
GetAsyncRange().Where(value => value % 2 == 0);

await foreach (int result in values) {
Console.WriteLine(result);
}

Но что, если нам нужно передать в Where асинхронный предикат? Where их не поддерживает. Но есть подходящий оператор WhereAwait:
IAsyncEnumerable<int> values = 
GetAsyncRange().WhereAwait(
async value => {
// Асинхронная работа для определения,
// должен ли элемент быть включён в результат
await Task.Delay(10);
return value % 2 == 0;
});

Методы LINQ для асинхронных потоков можно использовать и для обычных перечисляемых объектов, вызвав ToAsyncEnumerable() для любого IEnumerable<T>. Результат можно использовать с WhereAwait, SelectAwait и другими операторами, принимающими асинхронные делегаты.

Операторы LINQ для асинхронных потоков могут оканчиваться суффиксами Async и Await. Операторы, заканчивающиеся суффиксом Async, возвращают обычное значение, допускающее ожидание. Операторы с суффиксом Await получают асинхронный делегат. Т.е. Await в имени подразумевает, что они используют await внутри переданного делегата.

Пример WhereAwait был приведёт выше.

Суффикс Async применяется только к операторам терминации (termination operators), которые извлекают некоторое значение или выполняют некоторые вычисления и возвращают асинхронное скалярное значение. Пример такого оператора — CountAsync, версия Count для асинхронного потока, которая может подсчитать количество элементов, соответствующих некоторому предикату:
int count = await GetAsyncRange()
.CountAsync(value => value % 2 == 0);

Предикат может также быть асинхронным. В этом случае используется метод CountAwaitAsync, поскольку он получает асинхронного делегата и производит одно терминальное значение:
int count = await GetAsyncRange().CountAwaitAsync(
async value => {
await Task.Delay(10);
return value % 2 == 0;
});

Итого
- Операторы без суффиксов (Where, Select) получают синхронные делегаты и выдают асинхронную последовательность.
- Операторы, которые получают асинхронные делегаты, имеют суффикс Await (WhereAwait, SelectAwait), и выдают асинхронную последовательность.
- Операторы, возвращающие терминальное значение, имеют суффикс Async (CountAsync), а также могут иметь суффикс Await, если получают асинхронный делегат (CountAwaitAsync).

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


>>Click here to continue<<

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




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)