批量运行任务

时间:2018-11-11 03:40:52

标签: c# task task-parallel-library

我正在尝试理解System.Task,但是我不确定自己在做什么。我的目标是编写一种可批量处理图像的方法。

我的理解是正确的,如果使用batchSize = 3,该方法将在调用Task.WaitAll()时将3个任务排队并并行运行所有3个任务?

是否有更优雅的方式?

private static void ProcessImages(int batchSize)
{
      List<Task> tasks = new List<Task>();
      foreach (var image in ImageSource.ReadImages())
      {
            if(tasks.Count < batchSize)
            { 
                 tasks.Add(Task.Run(() => ImageProcessor.ProcessImage(image)));
            }
            else
            {
                 Task.WaitAll(tasks.ToArray());
                 tasks.Clear();
            }
      }
}

2 个答案:

答案 0 :(得分:3)

  

我的理解是正确的,在batchSize = 3的情况下,该方法   将排队3个任务,并尽快并行运行所有3个任务   Task.WaitAll()被称为?

虽然将任务添加到列表然后Task.WaitAll()的想法是正确的,但是您的代码很容易出故障,无法按预期工作。具体来说,如果无法用batchSize+1整除图像数量,则它将不为每个批次之后的图像执行任务,也将不为最后一批图像执行任务。

  

是否有更优雅的方式?

幸运的是,批量执行任务是非常普遍的要求,因此.NET已经包含了使其变得更容易的方法。使用PLINQ就是这样简单:

ImageSource.ReadImages()
    .AsParallel()
    .WithDegreeOfParallelism(batchSize)
    .ForAll(image => ImageProcessor.ProcessImage(image));

答案 1 :(得分:1)

另一种选择是使用Microsoft的Reactive Framework(NuGet“ System.Reactive”)。

然后这有效:

ImageSource
    .ReadImages()
    .ToObservable()
    .Select(image => Observable.Start(() => ImageProcessor.ProcessImage(image)))
    .Merge(maxConcurrent: 3)
    .Wait();

恕我直言,反应框架比任务要强大得多。