Как реализовать эффективный WhenEach, который передает IAsyncEnumerable результатов задачи? ⇐ 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, чтобы он работал достойно?
Я пытаюсь обновить свой набор инструментов новыми инструментами, предлагаемыми 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, чтобы он работал достойно?
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как реализовать эффективный WhenEach, который передает IAsyncEnumerable результатов задачи?
Anonymous » » в форуме C# - 0 Ответы
- 12 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Итерация IAsyncenumerable в функции, возвращающей IAsyncenumerable с отменой
Anonymous » » в форуме C# - 0 Ответы
- 26 Просмотры
-
Последнее сообщение Anonymous
-