打破parallel.foreach?
Posted
技术标签:
【中文标题】打破parallel.foreach?【英文标题】:Break parallel.foreach? 【发布时间】:2012-09-16 06:25:53 【问题描述】:如何跳出parallel.for 循环?
我有一个非常复杂的语句,如下所示:
Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
new Action<ColorIndexHolder>((ColorIndexHolder Element) =>
if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
Found = true;
break;
));
使用并行类,到目前为止我可以优化这个过程。然而;我不知道如何打破并行循环? break;
语句抛出以下语法错误:
没有可以中断或继续的封闭循环
【问题讨论】:
您是否希望循环的所有并行实例同时中断? 【参考方案1】:使用ParallelLoopState.Break
方法:
Parallel.ForEach(list,
(i, state) =>
state.Break();
);
或者在你的情况下:
Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
new Action<ColorIndexHolder, ParallelLoopState>((ColorIndexHolder Element, ParallelLoopState state) =>
if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
Found = true;
state.Break();
));
【讨论】:
完全正确。正要自己发布这个。 考虑一个顺序的 foreach 循环,可以保证处理由于任何原因导致中断的项目之前的项目。 Parallel.ForEach 项目的顺序不一定必须是处理它们的顺序?是否也保证 IEnumerable<...> 中的所有项目在调用 state.Break() 之前的所有项目都被处理,而在它之后的项目则不被处理?虽然前者可以以某种方式实现,但我根本不知道后者怎么可能。 @Hendrik Wiese:文档说:Calling the Break method informs the for operation that iterations after the current one don't have to execute. However, all iterations before the current one will still have to be executed if they haven't already.
和 there is no guarantee that iterations after the current one will definitely not execute.
那么state.Stop()
更适合可靠地实现预期结果,如下面的 Mike Perrenoud 和 MBentley 所述
有没有比state更直观的变量名?【参考方案2】:
您可以通过调用Parallel.For
或Parallel.ForEach
的重载来执行此操作,它们在循环状态中传递,然后调用ParallelLoopState.Break
或ParallelLoopState.Stop
。主要区别在于事情中断的速度 - 使用Break()
,循环将处理所有具有比当前“索引”更早的项目。使用Stop()
,它会尽快退出。
详情请见How to: Stop or Break from a Parallel.For Loop。
【讨论】:
+1,看起来我们这里的一些人的答案完全相同:) - 哦,我在其他评论人那里得到了你的支持。 感谢您的解释。您是否知道何时调用了 break 或 stop,是当前执行的迭代已完成还是在执行中途停止迭代? @CeejeeB 当前执行操作完成。【参考方案3】:你应该使用Any
,而不是foreach循环:
bool Found = ColorIndex.AsEnumerable().AsParallel()
.Any(Element => Element.StartIndex <= I
&& Element.StartIndex + Element.Length >= I);
Any
足够聪明,一旦知道结果必须为真,就会停下来。
【讨论】:
【参考方案4】:LoopState 无疑是一个很好的答案。我发现以前的答案有很多其他的东西,很难看到答案,所以这里是一个简单的案例:
using System.Threading.Tasks;
Parallel.ForEach(SomeTable.Rows(), (row, loopState) =>
if (row.Value == testValue)
loopState.Stop(); // Stop the ForEach!
// else do some other stuff here.
);
【讨论】:
【参考方案5】:只要使用可以提供的loopState
即可。
Parallel.ForEach<ColorIndexHolder>(ColorIndex.AsEnumerable(),
new Action<ColorIndexHolder>((Element, loopState) =>
if (Element.StartIndex <= I && Element.StartIndex + Element.Length >= I)
loopState.Stop();
));
以MSDN article 为例。
【讨论】:
以上是关于打破parallel.foreach?的主要内容,如果未能解决你的问题,请参考以下文章