是否可以在 Parallel.For 中定义执行顺序?

Posted

技术标签:

【中文标题】是否可以在 Parallel.For 中定义执行顺序?【英文标题】:Is it possible to define the execution order in Parallel.For? 【发布时间】:2011-11-27 13:44:33 【问题描述】:
// parameters.Count == 10
// actualFreeLicenses == 2
Parallel.For(0, parameters.Count, new ParallelOptions() 
                    
                        MaxDegreeOfParallelism = actualFreeLicenses
                    , i =>
                    
                        ExternalProgram(i);
                    
);

当我执行上面的代码时,我注意到传递给ExternalProgram 方法的i 的值是1 & 6,后来是2 & 7,后来是3 & 8 ...

如果我有 14 个参数和 2 个许可证,它总是启动 1 和 8,稍后启动 2 和 9 ...

是否可以定义顺序:前 1 和 2,后 3 和 4 等等?

【问题讨论】:

如果你有订单依赖,你需要使用延续。 @Sven 这不是必需的,但会很有用 - 在这里它会是题外话 【参考方案1】:

如何在并行循环的主体中使用 Queue/ConcurrentQueue 和出列项?这将确保保留顺序。

【讨论】:

对不起,评论后看到你的答案......对不起! +1 ;-)【参考方案2】:

如果您使用并行,则它们的执行顺序无关紧要,因此是“并行”。如果订单与您相关,您应该使用顺序工作流程。

【讨论】:

ExternalProgram(i) 需要很多时间,所以我需要多线程。有时我有更多的免费许可证。序列不是必需的,但会很有用 @Saint,你不能在线程完成工作后使用TaskContinueWith 运行一些序列吗? 您可以将队列用于项目的序列,以及从该队列请求其项目的多个线程。因此,您可以决定线程的方式和顺序。请不要忘记锁定对队列的访问权限。 @oberfreak: ... 或者使用 ConcurrentQueue【参考方案3】:

听起来您可能想使用 Parallel.ForEach 和 custom partitioner 代替 - 但不要忘记它并不是真正执行“1 & 6, then 2 & 7” - 它是在线程 1 上执行(比如说)1,在线程 2 上执行 6,然后在线程 2 上执行 7,等等。它不会像这样启动 pairs 进程。

如果您想启动进程组,您可能应该自己执行分组,然后循环遍历这些组串联,只提供组内的并行性,通过指定等于组大小的最大并行化程度。

【讨论】:

【参考方案4】:

如果您可以切换到使用ForEach(在生成一系列数字之后,也许使用IEnumerable.Range),您可以使用采用Partitioner<T> 的重载之一。第三个链接包括一个示例分区器,它一次提供一个元素。

【讨论】:

【参考方案5】:

运行时似乎正在查看您要使用的线程数并将工作负载划分为这些线程。例如第一个线程处理数据集的前半部分,第二个线程处理数据的后半部分。

【讨论】:

以上是关于是否可以在 Parallel.For 中定义执行顺序?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 Parallel.For 循环中使用相同的函数委托吗

测量Parallel.For的执行时间

Parallel.for 循环执行

线程和同步

C#并发编程之初识并行编程

Parallel.For 和 ConcurrentBag 给出不可预测的行为