Как использовать async перечисления?
У меня есть метод с этим возвращаемым типом:
public async Task<IEnumerable<T>> GetAll()
Он делает некоторые дальнейшие асинхронные вызовы (неизвестный номер), каждый из которых возвращает задачу перечислимого T, а затем хочет согласовать результаты для возврата.
var data1 = src1.GetAll();
var data2 = src2.GetAll();
var data3 = src3.GetAll(); //and so on
Теперь достаточно легко подождать всех и конкатрировать результаты, чтобы произвести единый перечислимый, но я хотел бы, чтобы перечисляемый был доступен, как только первый вызов вернется, с потенциальным ожиданием для вызывающего/перечислителя, если какие-либо вызовы все еще ожидается, когда закончится доступный результат.
Нужно ли мне руковать concat для этого, работая над отсутствием поддержки перечислителя, когда он завершает задачу < > ? Или там уже есть вызов библиотеки в TPL или в другом месте, что могло бы мне помочь. Я смотрел на IX, но он все еще находится на экспериментальном выпуске и не хочу его сбрасывать.
На стороне примечания, это то, что я пытаюсь использовать анти-шаблон? Я могу придумать одно осложнение, обработку исключений - со стороны вызывающего абонента, вызов может завершиться успешно, и он начнет использовать перечислимый, но он может взорваться на полпути через это...
Ответы
Ответ 1
Существует существующий проект под названием Async Enumerable, который точно отвечает на эту проблему.
Вы можете использовать его довольно легко.
Например:
IAsyncEnumerable<string> GetAsyncAnswers()
{
return AsyncEnum.Enumerate<string>(async consumer =>
{
foreach (var question in GetQuestions())
{
string theAnswer = await answeringService.GetAnswer(question);
await consumer.YieldAsync(theAnswer);
}
});
}
Это предоставляет IAsyncEnumerable<string>
, который возвращает один раз GetAnswer
. Вы можете внутренне выставить IAsyncEnumerable<T>
в своем случае и внутренне совершать вызовы внутри GetAll
.
что я пытаюсь создать анти-шаблон? Я могу придумать одно осложнение, обработка исключений - со стороны вызывающего абонента вызов может завершаться успешно, и он начинает использовать перечислимое, но может взорваться в середине этого...
Я бы так не сказал. У этого есть потенциально проблемы, такие как исключение, происходящее внутри во время одного из ожиданий, но это также может произойти внутри любого IEnumerable<T>
. Асинхронные последовательности - это то, что необходимо в сегодняшней реальности новых асинхронных API.