任务vs障碍

本文关键字:障碍 vs 任务 | 更新日期: 2023-09-27 17:49:22

所以我的问题如下:我有一个要处理的项目列表,我想并行处理这些项目,然后提交处理过的项目。

c#中的barrier类将允许我这样做——我可以并行运行线程来处理项目列表,当SignalAndWait被调用并且所有参与者都达到barrier时,我可以提交处理过的项目。

Task类也允许我在Task上执行此操作。WaitAll调用我可以等待所有任务完成,然后提交处理过的项目。如果我理解正确,每个任务将在它自己的线程上运行,而不是在同一线程上并行运行一堆任务。

  1. 我对问题的两种用法的理解是正确的吗?
  2. 两者之间有什么优势吗?
  3. 是否有更好的混合解决方案(障碍和任务?)

任务vs障碍

我对这个问题的两种用法的理解是否正确?

我认为你对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(...)方法允许您处理结果。

代码比使用任务或障碍简单得多。