我正在尝试理解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();
}
}
}
答案 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();
恕我直言,反应框架比任务要强大得多。