任务与障碍
Task vs Barrier
所以我的问题如下:我有一个要处理的项目列表,我想并行处理这些项目然后提交已处理的项目。
C# 中的障碍 class 允许我这样做 - 我可以 运行 线程并行处理项目列表,当调用 SignalAndWait 并且所有参与者都遇到障碍时我可以提交已处理的项目。
任务 class 也将允许我执行此操作 - 在 Task.WaitAll 调用中,我可以等待所有任务完成并提交已处理的项目。如果我理解正确,每个任务将 运行 在它自己的线程上,而不是在同一线程上并行执行一堆任务。
- 我对问题的两种用法的理解是否正确?
- 两者之间有什么优势吗?
- 有没有更好的混合解决方案(障碍和任务?)。
Is my understand correct on both usages for the problem?
我觉得你对Barrier
有误解class。 The docs say:
A barrier is a user-defined synchronization primitive that enables multiple threads (known as participants) to work concurrently on an algorithm in phases.
屏障是一种同步原语。将它与可以并行计算的工作单元(例如 Task
进行比较是不正确的。
屏障可以通知所有线程等待,直到所有其他线程完成一些工作并检查该工作。就其本身而言,它没有并行计算能力,也没有背后的线程模型。
Is there any advantage between one over the other?
至于问题1,你看这无关紧要。
Is there any way a hybrid solution is better (barrier and tasks?).
对于您的情况,我完全不确定是否需要它。如果您只是想对一组项目并行执行 CPU 绑定计算,那么您有 Parallel.ForEach
正是为了这个目的。它将对一个可枚举对象进行分区并并行调用它们,然后阻塞直到计算完整个集合。
我没有直接回答你的问题,因为我认为使用障碍和任务只会让你的代码变得比它需要的更复杂。
我建议为此使用 Microsoft 的 Reactive Framework - 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(...)
方法允许您处理结果。
代码比使用任务或障碍简单得多。
所以我的问题如下:我有一个要处理的项目列表,我想并行处理这些项目然后提交已处理的项目。
C# 中的障碍 class 允许我这样做 - 我可以 运行 线程并行处理项目列表,当调用 SignalAndWait 并且所有参与者都遇到障碍时我可以提交已处理的项目。
任务 class 也将允许我执行此操作 - 在 Task.WaitAll 调用中,我可以等待所有任务完成并提交已处理的项目。如果我理解正确,每个任务将 运行 在它自己的线程上,而不是在同一线程上并行执行一堆任务。
- 我对问题的两种用法的理解是否正确?
- 两者之间有什么优势吗?
- 有没有更好的混合解决方案(障碍和任务?)。
Is my understand correct on both usages for the problem?
我觉得你对Barrier
有误解class。 The docs say:
A barrier is a user-defined synchronization primitive that enables multiple threads (known as participants) to work concurrently on an algorithm in phases.
屏障是一种同步原语。将它与可以并行计算的工作单元(例如 Task
进行比较是不正确的。
屏障可以通知所有线程等待,直到所有其他线程完成一些工作并检查该工作。就其本身而言,它没有并行计算能力,也没有背后的线程模型。
Is there any advantage between one over the other?
至于问题1,你看这无关紧要。
Is there any way a hybrid solution is better (barrier and tasks?).
对于您的情况,我完全不确定是否需要它。如果您只是想对一组项目并行执行 CPU 绑定计算,那么您有 Parallel.ForEach
正是为了这个目的。它将对一个可枚举对象进行分区并并行调用它们,然后阻塞直到计算完整个集合。
我没有直接回答你的问题,因为我认为使用障碍和任务只会让你的代码变得比它需要的更复杂。
我建议为此使用 Microsoft 的 Reactive Framework - 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(...)
方法允许您处理结果。
代码比使用任务或障碍简单得多。