Как реализовать эффективный WhenEach, который передает IAsyncEnumerable результатов задачи?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Гость
 Как реализовать эффективный WhenEach, который передает IAsyncEnumerable результатов задачи?

Сообщение Гость »


Я пытаюсь обновить свой набор инструментов новыми инструментами, предлагаемыми C# 8, и один из методов, который кажется особенно полезным, — это версия Task.WhenAll, которая возвращает IAsyncEnumerable. Этот метод должен передавать результаты задачи в потоковом режиме, как только они станут доступны, поэтому называть его WhenAll не имеет особого смысла. WhenEach звучит более уместно. Сигнатура метода:

public static IAsyncEnumerable WhenEach(Task[] задачи); Этот метод можно использовать следующим образом:

var Tasks = новая Задача[] { ПроцессАсинк(1, 300), ПроцессАсинк(2, 500), ПроцессАсинк(3, 400), ПроцессАсинк(4, 200), ПроцессАсинк(5, 100), }; await foreach (результат int в WhenEach(tasks)) { Console.WriteLine($"Обработано: {результат}"); } статическая асинхронная задача Task ProcessAsync (целочисленный результат, целочисленная задержка) { ждать Task.Delay(задержка); вернуть результат; } Ожидаемый результат:

Обработано: 5
Обработано: 4
Обработано: 1
Обработано: 3
Обработано: 2

Мне удалось написать базовую реализацию с использованием метода Task.WhenAny в цикле, но с этим подходом есть проблема:

public static async IAsyncEnumerable WhenEach( Task[] задачи) { вар hashSet = новый HashSet(задачи); пока (hashSet.Count > 0) { вар задача = ждут Task.WhenAny(hashSet).ConfigureAwait(false); выходной возврат ждут задачи.ConfigureAwait(false); hashSet.Remove (задача); } } Проблема в производительности. Метод Task.WhenAny должен следить за завершением всех предоставленных задач, и он делает это путем присоединения и отсоединения продолжений, поэтому его повторный вызов в цикле приводит к вычислительной сложности O(n²). Моя наивная реализация с трудом справляется с обработкой 10 000 задач. На моей машине накладные расходы составляют почти 10 секунд. Мне бы хотелось, чтобы этот метод был почти таким же производительным, как встроенный Task.WhenAll, который мог бы легко обрабатывать сотни тысяч задач. Как я могу улучшить метод WhenEach, чтобы он работал достойно?
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как реализовать эффективный WhenEach, который передает IAsyncEnumerable результатов задачи?
    Anonymous » » в форуме C#
    0 Ответы
    12 Просмотры
    Последнее сообщение Anonymous
  • Итерация IAsyncenumerable в функции, возвращающей IAsyncenumerable с отменой
    Anonymous » » в форуме C#
    0 Ответы
    26 Просмотры
    Последнее сообщение Anonymous
  • Как дождаться всех результатов от IAsyncEnumerable<>?
    Anonymous » » в форуме C#
    0 Ответы
    21 Просмотры
    Последнее сообщение Anonymous
  • Получение 2 -го `iAsyncenumerator <>` из того же `jasyncenumerable <>` на основе `task.wheneach <>` method
    Anonymous » » в форуме C#
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous
  • Получение 2 -го `iAsyncenumerator <>` из того же `jasyncenumerable <>` на основе `task.wheneach <>` method
    Anonymous » » в форуме C#
    0 Ответы
    14 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»