控制Parallel.For循环的执行
我们都知道,在普通for循环中,我们可以使用break或者continue关键词来控制for循环的执行,在一些特殊的情况下跳出for循环的执行或者是继续for循环的下一次执行。遗憾的是,这两个关键字不能使用在Parallel.For循环中。那么我们又如何控制Parallel.For循环的执行呢?Parallel.For函数提供了一些重载版本,这些重载的Parallel.For函数可以接受一个Action作为参数,而我们可以利用ParallelLoopState对象来控制Parallel.For函数的执行,ParallelLoopState对象是由运行时在后台创建的,我们还可以将ParallelLoopState命名为我们喜欢的名字,比如PrimeLoopState等等。这个对象有两个函数,Stop和Break,可以分别用来控制Parallel.For的执行。
其中,如果我们调用Stop,表示Parallel.For的执行立刻停止,无论其他执行单元是否达到停止的条件。而如果我们使用Break,则表示满足条件的当前执行单元立刻停止,而对于其他执行单元,可能会满足停止条件而通过Break停止,也可能在其执行过程中始终无法满足停止条件,从而全部执行完毕,自然停止。当所有执行单元停止后,Parallel.For函数才停止执行并退出。下面的代码演示了Break和Stop两个函数的差别:
private static void StopParallelFor()
{
int nTotal = 0;
Parallel.For(1, 100, (i, loopState) =>
{
// 当某一个循环单元的数大于30,
// 则停止Parallel.For的执行
if ( i > 30)
{
// 停止并退出Parallel.For
loopState.Stop();
return;
}
Console.WriteLine("Current Nummber: {0} ", i);
Interlocked.Increment(ref nTotal);
});
// 输出结果
Console.WriteLine("Total Accessed: {0} ", nTotal);
}
// 输出:
/* Current Nummber: 1
Current Nummber: 2
Total Accessed: 2
*/
// 跳出Parallel.For的循环
private static void BreakParallelFor()
{
int nTotal = 0;
Parallel.For(1, 100, (i, loopState) =>
{
// 当某一个循环单元的数大于30,
// 则跳出当前执行单元,等待其他执行单元结束
// 所有执行单元结束后退出Parallel.For的执行
if (i > 30)
{
// 跳出当前执行单元
loopState.Break();
return;
}
Console.WriteLine("Current Nummber: {0} ", i);
Interlocked.Increment(ref nTotal);
});
// 输出结果
Console.WriteLine("Total Accessed: {0} ", nTotal);
}
// 输出:
/* Current Nummber: 1
Current Nummber: 2
Current Nummber: 22
Current Nummber: 23
Current Nummber: 27
...
Current Nummber: 20
Current Nummber: 21
Total Accessed: 30
*/
从代码中我们可以看出,调用Break函数,只会停止满足条件的当前执行单元的执行,而其他执行单元是否停止,则要靠他们自己判断。而调用Stop函数,则会立刻停止所有执行单元,退出整个Parallel.For函数。
另外,Parallel.For方法有一个ParallelLoopResult类型的返回值,可以通过此返回值的IsCompleted属性来判断Parallel.For方法启动的所有任务是否运行都结束