bbr*_*ez1 5 c# parallel-processing parallel.foreach
什么是最有效的暂停和停止(在它结束之前)parallel.foreach的方法?
Parallel.ForEach(list, (item) =>
{
doStuff(item);
});
Run Code Online (Sandbox Code Playgroud)
Sco*_*ain 11
Damien_The_Unbeliver有一个很好的方法,但只有你想让一些外部进程停止循环.如果你想让循环突然出现就像使用break普通循环for或foreach循环一样,你需要使用一个带有ParallelLoopState循环体参数之一的重载.ParallelLoopState有两个与你想做的事情相关的功能,Stop()和Break().
该函数Stop()将在系统最早的方便时停止处理元素,这意味着在调用Stop()之后可以执行更多的迭代,并且不能保证在您停止的元素之前的元素甚至已经开始处理.
该函数Break()执行完全相同,Stop()但它也将评估IEnumerable您调用的项之前的所有元素Break().当您不关心处理元素的顺序时,这非常有用,但您必须处理所有元素,直到您停止的点为止.
检查foreach返回的ParallelLoopResult,看看foreach是否提前停止,如果使用了Break(),它处理的编号最小的项目是什么.
Parallel.ForEach(list, (item, loopState) =>
{
bool endEarly = doStuff(item);
if(endEarly)
{
loopState.Break();
}
}
);
//Equivalent to the following non parallel version, except that if doStuff ends early
// it may or may not processed some items in the list after the break.
foreach(var item in list)
{
bool endEarly = doStuff(item);
if(endEarly)
{
break;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个更实际的例子
static bool[] list = new int[]{false, false, true, false, true, false};
long LowestElementTrue()
{
ParallelLoopResult result = Parallel.ForEach(list, (element, loopState) =>
{
if(element)
loopState.Break();
}
if(result.LowestBreakIteration.IsNull)
return -1;
else
return result.LowestBreakIteration.Value;
}
Run Code Online (Sandbox Code Playgroud)
无论它如何分割工作,它总是返回2作为答案.
假设处理器调度两个线程来处理它,第一个线程处理元素0-2,第二个线程处理元素3-5.
Thread 1: Thread 2 0, False, continue next 3, False, continue next 1, False, continue next 4, True, Break 2, True, Break 5, Don't process Broke
现在最低的索引Break是从2调用的,所以ParallelLoopResult.LowestBreakIteration每次都会返回2,无论线程是如何分解的,因为它总是处理到数字2.
这里有一个如何使用Stop的例子.
static bool[] list = new int[]{false, false, true, false, true, false};
long FirstElementFoundTrue()
{
long currentIndex = -1;
ParallelLoopResult result = Parallel.ForEach(list, (element, loopState, index) =>
{
if(element)
{
loopState.Stop();
//index is a 64 bit number, to make it a atomic write
// on 32 bit machines you must either:
// 1. Target 64 bit only and not allow 32 bit machines.
// 2. Cast the number to 32 bit.
// 3. Use one of the Interlocked methods.
Interlocked.Exchange (ref currentIndex , index);
}
}
return currentIndex;
}
Run Code Online (Sandbox Code Playgroud)
根据它分割工作的方式,它将返回2或4作为答案.
假设处理器调度两个线程来处理它,第一个线程处理元素0-2,第二个线程处理元素3-5.
Thread 1: Thread 2 0, False, continue next 3, False, continue next 1, False, continue next 4, True, Stop 2, Don't process, Stopped 5, Don't process, Stopped
在这种情况下,它将返回4作为答案.让我们看看相同的过程,但如果它处理所有其他元素而不是0-2和3-5.
Thread 1: Thread 2 0, False, continue next 1, False, continue next 2, True, Stop 3, False, continue next 4, Don't process, Stopped 5, Don't process, Stopped
这次它将返回2而不是4.