任务vs障碍
本文关键字:障碍 vs 任务 | 更新日期: 2023-09-27 17:49:22
所以我的问题如下:我有一个要处理的项目列表,我想并行处理这些项目,然后提交处理过的项目。
c#中的barrier类将允许我这样做——我可以并行运行线程来处理项目列表,当SignalAndWait被调用并且所有参与者都达到barrier时,我可以提交处理过的项目。
Task类也允许我在Task上执行此操作。WaitAll调用我可以等待所有任务完成,然后提交处理过的项目。如果我理解正确,每个任务将在它自己的线程上运行,而不是在同一线程上并行运行一堆任务。
- 我对问题的两种用法的理解是正确的吗?
- 两者之间有什么优势吗?
- 是否有更好的混合解决方案(障碍和任务?)
我对这个问题的两种用法的理解是否正确?
我认为你对Barrier
类有误解。医生说:
barrier是一个用户定义的同步原语,它允许多个线程(称为参与者)分阶段并发地处理一个算法。
barrier是一个同步原语。将其与可以并行计算的工作单元(如Task
)进行比较是不正确的。
barrier可以通知所有线程等待,直到所有其他线程完成某些工作并检查该工作。它本身没有并行计算能力,也没有线程模型。
两者之间有什么优势吗?
关于问题1,你看这是不相关的。
对于你的情况,我不确定是否有必要。如果你只是想在一个项目集合上并行地做CPU约束计算,你有是否有更好的混合解决方案(障碍和任务?)。
Parallel.ForEach
正是为了这个目的。它将划分一个可枚举对象并并行调用它们,并阻塞,直到计算完整个集合。
我不直接回答你的问题,因为我认为处理障碍和任务只会使你的代码比需要的更复杂。
我建议使用微软的响应式框架——NuGet"Rx-Main"——因为它让整个问题变得超级简单。
代码如下:
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()
获取单个结果的序列,并将其更改为单个结果数组。然后,.Subscribe(...)
方法允许您处理结果。
代码比使用任务或障碍简单得多。