1

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

C# 中的屏障类将允许我执行此操作 - 我可以并行运行线程来处理项目列表,当调用 SignalAndWait 并且所有参与者都遇到障碍时,我可以提交已处理的项目。

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

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

2 回答 2

5

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

我认为你对Barrier班级有误解。文档说

屏障是用户定义的同步原语,它允许多个线程(称为参与者)分阶段在算法上同时工作。

屏障是一种同步原语。将其与可以并行计算的工作单元(例如 a )进行Task比较是不正确的。

屏障可以向所有线程发出信号以等待所有其他线程完成某些工作并检查该工作。它本身没有并行计算能力,也没有背后的线程模型。

两者之间有什么优势吗?

至于问题1,你看这无关紧要。

有什么混合解决方案更好的方法(障碍和任务?)。

在你的情况下,我不确定它是否需要。如果您只想在一组项目上并行执行 CPU 绑定计算,那么您Parallel.ForEach完全可以达到这个目的。它将划分一个可枚举并并行调用它们,并阻塞直到整个集合被计算。

于 2015-05-17T04:56:25.080 回答
0

我没有直接回答你的问题,因为我认为处理障碍和任务只会让你的代码比它需要的更复杂。

我建议为此使用微软的反应式框架——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(...)方法允许您处理结果。

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

于 2015-05-17T05:01:50.147 回答