Выполнять ограниченное количество задач одновременно - PullRequest
0 голосов
/ 22 февраля 2019

Учитывая, что у меня есть IEnumerable<Func<Task>> для генерации некоторых (гусеничных) -задач, которые я хочу выполнить одновременно, как я могу установить верхнюю границу для параллелизма?

Например, я не хочу, чтобы больше5 из этих задач выполняются одновременно.С другой стороны, всегда должно быть запущено 5 задач, если это возможно.

Мой текущий подход заключается в следующем:

    public static async Task ExecuteConcurrent(IEnumerable<Func<Task>> taskGenerators, int maxDegreeOfConcurrency)
    {
        var executingTasks = new HashSet<Task>();
        foreach (var taskGenerator in taskGenerators) {
            while (executingTasks.Count >= maxDegreeOfConcurrency) {
                executingTasks.Remove(await Task.WhenAny(executingTasks));
            }

            executingTasks.Add(taskGenerator());
        }

        await Task.WhenAll(executingTasks);
    }

Мне интересно, есть ли лучший способ сделать это?Может быть, метод уже доступен?

Спасибо

1 Ответ

0 голосов
/ 22 февраля 2019

Похоже на работу для Поток данных TPL

Преимущества:

  1. Хорошо работает с async и await и обоими Процессор привязан и IO ограничен рабочие нагрузки
  2. Вы можете ограничить параллелизм с помощью MaxDegreeOfParallelism и многих других опций
  3. Вы можете Цепочка itв более сложные PipeLines
  4. Хорошо работает с Реактивными расширениями
  5. все это создано для вас мистером Параллелем Стивеном Тубом

Nuget System.Threading.Tasks.Dataflow


Очень простой пример

public static async Task DoWorkLoads(List<IPAddress> addresses)
{
   var options = new ExecutionDataflowBlockOptions
                     {
                        MaxDegreeOfParallelism = 50 // limit here
                     };

   var block = new ActionBlock<SomeObject>(MyMethodAsync, options);

   foreach (var ip in addresses)
      block.Post(ip);

   block.Complete();
   await block.Completion;

}

...

public async Task MyMethodAsync(SomeObject obj)
{
    // await something here
}
...