§ ITPOW >> 文档 >> C#

.NET Parallel 并行循环

作者:vkvi 来源:ITPOW(原创) 日期:2021-3-9

.NET Framework 4.0 开始,加入了 Parallel 并行循环语句,这个语句类似于线程,但是用起来更简单。

Parallel.For 与 Parallel.ForEach

using System.Threading.Tasks;

Parallel.For(0, count, index =>
{
    // 循环 count 次,index 为 [0, count)
    // do something
}); // 此处 For 有 3 个参数,第 3 个参数是个方法,该方法有 1 个参数。

Parallel.ForEach(list, item =>
{
    // 循环 list.Count 次
    // do something
}); // 此处 ForEach 有 2 个参数,第 2 个参数是个方法,该方法有 1 个参数。

原理

就是开多个线程,由于是多线程,所以:

  • 内部循环的顺序并不会得到保证,也就是说并不是执行完了 list[0],再执行 list[1]。

  • 内部使用共享资源时要注意锁定

  • 循环次数较少时,没必要用。

比线程方便在哪里?

既然还是线程,那比 new Thread 方便在哪里呢?那就是:在 Parallel 执行完之前,主线程不会执行下一句代码。

Console.WriteLine("我准备进循环了");
Parallel.For(0, 3, index =>
{
	Thread.Sleep(100);
	Console.WriteLine(index);
}); // 此处 For 有 3 个参数,第 3 个参数是个方法,该方法有 1 个参数。
Console.WriteLine("我已经出循环了"); // 这句总是在 Parallel 干完了(提前 Stop()、Break() 也算),才会执行。而直接创建线程,则不具备这种能力。

不过 new Thread 更灵活,我们可以控制多少个 Thread。

如何提前退出循环?

Parallel.For(0, 3, (int index, ParallelLoopState state) =>
{
	state.Stop();
	Console.WriteLine(index);
}); // 此处 For 有3 个参数,第 3 个参数是个方法,该方法有 2 个参数。

如上,state.Stop() 一被调用就会退出循环,不过当前循环后面的代码 Console.WriteLine(index); 这句,还是会执行的。

Stop() 与 Break() 有何区别?

上述使用 Stop() 退出了循环,其实 Break() 也是可以的,那二者有什么区别呢?

共同点:不会中止已经开始的循环项。

不同点:Break() 是:如果还有比当前 index 小的循环项没有被执行,那就等它们执行,再退出;至于那些比当前 index 大的循环项,就不要管了(已经在执行的继续执行,没执行的不再调用了)。

如何知道执行完毕?

var result = Parallel.For(0, 3, (int index, ParallelLoopState state) =>
{
	state.Break();
	// do something
});

if (result.IsCompleted) // 并不表示 For、ForEach 语句执行完没有,而是表示其中的循环项是否都循环了。
{
	Console.WriteLine("把每个循环都执行了。");
}
else
{
	// 注意:即使所有的循环都执行了,但是只要调用了 Break() 或 Stop(),哪怕是退出循环的最后一刻调用了,都会进这里。
	if (result.LowestBreakIteration != null)
	{
		Console.WriteLine("使用 Break 提前退出了循环。");
	}
	else
	{
		Console.WriteLine("使用 Stop 提前退出了循环。");
	}
}

注意:即使所有的循环都执行了,但是只要调用了 Break() 或 Stop(),哪怕是退出循环的最后一刻调用了,IsCompleted 都为 false。

相关文章