所以我的问题如下:我有一个要处理的项目列表,我想并行处理这些项目,然后提交已处理的项目。
C#中的barrier类允许我这样做 - 我可以并行运行线程来处理项目列表,当调用SignalAndWait并且所有参与者都遇到障碍时我可以提交已处理的项目。
Task类也允许我这样做 - 在Task.WaitAll调用上我可以等待所有任务完成,我可以提交已处理的项目。如果我理解正确,每个任务都会在它自己的线程上运行而不是在同一个线程上并行执行大量任务。
答案 0 :(得分:4)
我对这个问题的两种用法都理解正确吗?
我认为你对Barrier
课程有误解。 The docs say:
屏障是用户定义的同步原语,它允许多个线程(称为参与者)分阶段同时处理算法。
屏障是同步原语。将其与可能并行计算的工作单元(例如Task
)进行比较是不正确的。
屏障可以通知所有线程等待所有其他线程完成某些工作并检查该工作。它本身没有并行计算功能,也没有后面的线程模型。
一方之间有什么优势吗?
至于问题1,你会发现这是无关紧要的。
混合解决方案有没有更好的方法(障碍和任务?)。
在你的情况下,我根本不确定它是否需要。如果你想在一组项目上并行地进行CPU绑定计算,那么你就完全有Parallel.ForEach
的目的。它将对可枚举进行分区并并行调用它们,并阻塞直到计算完整个集合。
答案 1 :(得分:0)
我没有直接回答你的问题,因为我认为使用障碍和任务只会使你的代码变得比它需要的更复杂。
我建议使用Microsoft的Reactive Framework - NuGet" Rx-Main" - 因为它只是使整个问题变得非常简单。
以下是代码:
pizza = input_checker("Do you like pizza? ", yes + no)
查询将项目列表转换为可观察对象,然后使用var query =
from item in items.ToObservable()
from processed in Observable.Start(() => processItem(item))
select new { item, processed };
query
.ToArray()
.Subscribe(processedItems =>
{
/* commit the processed items */
});
处理每个项目。这可以根据需要最佳地触发新线程。 Observable.Start(...)
获取单个结果的序列并将其更改为单个结果数组。然后.ToArray()
方法允许您处理结果。
代码比使用任务或障碍简单得多。