如何限制 Parallel.ForEach?

Posted

技术标签:

【中文标题】如何限制 Parallel.ForEach?【英文标题】:How can I limit Parallel.ForEach? 【发布时间】:2012-03-06 14:59:08 【问题描述】:

我有一个 Parallel.ForEach() 异步循环,我用它下载一些网页。我的带宽有限,因此我每次只能下载 x 页,但 Parallel.ForEach 会执行所需网页的整个列表。

有没有办法在运行 Parallel.ForEach 时限制线程数或任何其他限制器?

演示代码:

Parallel.ForEach(listOfWebpages, webpage => 
  Download(webpage);
);

真正的任务与网页无关,因此创造性的网页抓取解决方案无济于事。

【问题讨论】:

@jKlaus 如果列表未修改,例如这只是一组网址,我真的看不出问题吗? @Shiv,如果有足够的时间,您将... 计算您的执行次数并将其与列表的计数进行比较。 @jKlaus 你说什么会出错? @jKlaus 您正在修改非线程安全元素(整数)。我希望它在那种情况下不起作用。另一方面,OP 不会修改任何需要线程安全的东西。 @jKlaus 这是一个正确设置计数的 Parallel.ForEach 示例 > dotnetfiddle.net/moqP2C。 MSDN 链接:msdn.microsoft.com/en-us/library/dd997393(v=vs.110).aspx 【参考方案1】:

您可以在ParallelOptions 参数中指定MaxDegreeOfParallelism

Parallel.ForEach(
    listOfWebpages,
    new ParallelOptions  MaxDegreeOfParallelism = 4 ,
    webpage =>  Download(webpage); 
);

MSDN:Parallel.ForEach

MSDN:ParallelOptions.MaxDegreeOfParallelism

【讨论】:

它可能不适用于这种特殊情况,但我想我会把它扔掉,以防有人对此感到疑惑并发现它有用。在这里,我使用了 75%(向上取整)的处理器数量。 var opts = new ParallelOptions MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 1.0)) ; 只是为了节省其他人必须在文档中查找它,传递 -1 的值与根本不指定它是一样的:"如果 [值] 是 - 1、并发运行的操作数没有限制” 从文档中我不清楚 - 将 MaxDegreeOfParallelism 设置为 4(例如)是否意味着将有 4 个线程,每个线程运行 1/4 的循环迭代(一轮 4 个线程调度),还是每个线程仍然进行一次循环迭代,而我们只是限制了并行运行的数量? 明确内核和线程不是一回事。根据 CPU 的不同,每个内核有不同数量的线程,通常每个内核 2 个。例如,如果您有一个 4 核 CPU,每个内核有 2 个线程,那么您最多有 8 个线程。调整@jKlaus 评论var opts = new ParallelOptions MaxDegreeOfParallelism = Convert.ToInt32(Math.Ceiling((Environment.ProcessorCount * 0.75) * 2.0)) ;。链接到线程与内核 - askubuntu.com/questions/668538/…【参考方案2】:

可以使用 ParallelOptions 并设置 MaxDegreeOfParallelism 来限制并发线程数:

Parallel.ForEach(
    listOfwebpages, 
    new ParallelOptionsMaxDegreeOfParallelism=2, 
    webpage => Download(webpage););     

【讨论】:

【参考方案3】:

使用另一个Parallel.Foreach 重载,它采用ParallelOptions 实例,并设置MaxDegreeOfParallelism 以限制并行执行的实例数。

【讨论】:

【参考方案4】:

对于 VB.net 用户(语法很奇怪,很难找到)...

Parallel.ForEach(listOfWebpages, New ParallelOptions() With .MaxDegreeOfParallelism = 8, Sub(webpage)
......end sub)  

【讨论】:

以上是关于如何限制 Parallel.ForEach?的主要内容,如果未能解决你的问题,请参考以下文章

.Net 中的多个 Parallel.ForEach 循环

Parallel.ForEach 没有提供更多内核的加速[关闭]

如何将此 foreach 代码转换为 Parallel.ForEach?

如何从 Parallel.ForEach 收集返回值?

我在 Parallel.ForEach 循环中收到 TaskCanceledException,如何解决?

打破parallel.foreach?