Parallel.Foreach C# 暂停和停止函数?
暂停和停止(在结束之前)parallel.foreach 的最有效方法是什么?
Parallel.ForEach(list, (item) =>
{
doStuff(item);
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Damien_The_Unbeliver 有一个很好的方法,但前提是您想让某些外部进程停止循环。如果您想让循环像在正常的
for
或foreach
循环中使用break
一样中断,您将需要使用 具有 href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallelloopstate.aspx" rel="nofollow noreferrer">ParallelLoopState
作为一个循环体的参数。ParallelLoopState
有两个与您想要执行的操作相关的函数,Stop()
和Break()
。函数
Stop()
将在系统方便的时候尽早停止处理元素,这意味着在调用 Stop() 后可以执行更多迭代,并且不能保证处理元素在您停止的元素甚至开始处理之前出现。函数
Break()
的执行方式与Stop()
完全相同,但它也会评估位于该项目之前的IEnumerable
的所有元素。您调用了Break()
。当您不关心元素的处理顺序,但必须处理所有元素直到停止点时,这非常有用。检查从 foreach 返回的 ParallelLoopResult查看 foreach 是否提前停止,以及是否使用了
Break()
,它处理的最小编号的项目是什么。这是一个更实际的例子,
无论它如何分配工作,它总是返回 2 作为答案。
假设处理器调度两个线程来处理此问题,第一个线程处理元素 0-2,第二个线程处理元素 3-5。
现在,调用的最低索引 Break 是 2,因此 ParallelLoopResult.LowestBreakIteration 每次都会返回 2,无论线程如何分解,因为它始终会处理到数字 2。
这里是一个示例如何使用停止。
根据它如何分配工作,它将返回 2 或 4 作为答案。
假设处理器调度两个线程来处理此问题,第一个线程处理元素 0-2,第二个线程处理元素 3-5。
在本例中,它将返回 4 作为答案。让我们看看相同的过程,但它是否处理所有其他元素而不是 0-2 和 3-5。
这次它将返回 2 而不是 4。
Damien_The_Unbeliver has a good method, but that is only if you want to have some outside process stop the loop. If you want to have the loop break out like using a
break
in a normalfor
orforeach
loop you will need to use a overload that has aParallelLoopState
as one of the parameters of the loop body.ParallelLoopState
has two functions that are relevant to what you want to do,Stop()
andBreak()
.The function
Stop()
will stop processing elements at the system's earliest convenience which means more iterations could be performed after you call Stop() and it is not guaranteed that the elements that came before the element you stopped at have even begun to process.The function
Break()
performs exactly the same asStop()
however it will also evaluate all elements of theIEnumerable
that came before the item that you calledBreak()
on. This is useful for when you do not care what order the elements are processed in, but you must process all of the elements up to the point you stopped.Inspect the ParallelLoopResult returned from the foreach to see if the foreach stopped early, and if you used
Break()
, what is the lowest numbered item it processed.Here is a more practical example
No matter how it splits up the work it will always return 2 as an answer.
let's say the processor dispatches two threads to process this, the first thread processes elements 0-2 and the 2nd thread processes elements 3-5.
Now the lowest index Break was called from was 2 so
ParallelLoopResult.LowestBreakIteration
will return 2 every time, no-matter how the threads are broken up as it will always process up to the number 2.Here an example how how Stop could be used.
Depending how it splits up the work it will either return 2 or 4 as the answer.
let's say the processor dispatches two threads to process this, the first thread processes elements 0-2 and the 2nd thread processes elements 3-5.
In this case it will return 4 as the answer. Lets see the same process but if it processes every other element instead of 0-2 and 3-5.
This time it will return 2 instead of 4.
为了能够停止 Parallel.ForEach,您可以使用接受
ParallelOptions
参数,并包含一个CancellationToken
在这些选项中。有关详细信息,请参阅取消。
至于暂停,一般来说,我不明白你为什么要这样做。您可能正在寻找Barrier(用于协调多个线程之间的工作,比如说它们是否都需要在继续 B 部分之前完成 A 部分),但我认为您不会将其与 Parallel.ForEach 一起使用,因为您不这样做不知道会有多少参与者 是。
To be able to stop a
Parallel.ForEach
, you can use one of the overloads that accepts aParallelOptions
parameter, and include aCancellationToken
in those options.See Cancellation for more details.
As for pausing, I can't think why you'd want to do that, in general. You might be looking for a Barrier (which is used to coordinate efforts between multiple threads, say if they all need to complete part A before continuing to part B), but I wouldn't think that you'd use that with
Parallel.ForEach
, since you don't know how many participants there will be.