如何限制 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?的主要内容,如果未能解决你的问题,请参考以下文章
Parallel.ForEach 没有提供更多内核的加速[关闭]
如何将此 foreach 代码转换为 Parallel.ForEach?