【C# Parallel】ParallelLoopState
总结
总之,要编写一个健壮的并行循环,必须在并行循环体中检测 ParallelLoopState 对象的 IsExceptional, IsStopped 和 LowestBreakIteration 三个属性,出于简化编程的目的, ParallelLoopState 提供了一个 ShouldExitCurrentIteration 属性,当Stop()\cancel()时,ShouldExitCurrentIteration等于true。
方法 | 属性 | |
异常 | IsExceptional | ShouldExitCurrentIteration |
Stop | IsStopped | ShouldExitCurrentIteration |
Break | LowestBreakIteration(循环索引起始是0) |
stop
可以多次被调用,对应的属性IsExceptional、IsStopped。当发生break后,IsStopped等于true,ShouldExitCurrentIteration等于true。
ParallelLoopResult plr= Parallel.For(1,20,(index, LoopState) =>{ if (i == 10) { // 当某一个循环单元的数==10, // 则停止所有线程的Parallel.For的执行,已经执行循环执行完当前一轮循环后停止,未执行的循环直接停止执行。 LoopState.Stop();//执行Stop()LowestBreakIteration为空,Stop/Break互斥两个只能有一个执行,Stop停止循环比Break快。
Console.WriteLine("ShouldExitCurrentIteration " + LoopState.ShouldExitCurrentIteration);//break 执行后ShouldExitCurrentIteration为true return;//不加return,可能会发生该进程资源未释放。 } Console.WriteLine(index+ " ThreadId" + Environment.CurrentManagedThreadId); }); Console.WriteLine("LowestBreakIteration:" + plr.LowestBreakIteration);
break
可以多次被调用。对应的属性LowestBreakIteration、ShouldExitCurrentIteration。当发生break后,LowestBreakIteration等于最小那个index,ShouldExitCurrentIteration等于false
由于多线程执行,所以会有多个线程同时发生break,LowestBreakIteration取for循环最小那个index 。
ParallelLoopResult plr= Parallel.For(1,20,(index, LoopState) =>{ if (index == 10) { // 当某一个循环单元的数==10, // 则首先停止当前 线程的Parallel.For的执行 //其他线程的For 满足条件则继续执行,直到满足条件或完成 // 所有执行单元结束后退出Parallel.For的执行 LoopState.Break();//LowestBreakIteration有值,Stop/Break互斥两个只能有一个执行,Stop停止循环比Break快。 Console.WriteLine("ShouldExitCurrentIteration " + LoopState.ShouldExitCurrentIteration);//break 执行后对ShouldExitCurrentIteration为false 没影响
return;//不加return,可能会发生该进程资源未释放。 } Console.WriteLine(index+ " ThreadId" + Environment.CurrentManagedThreadId); }); Console.WriteLine("LowestBreakIteration:" + plr.LowestBreakIteration);
CancellationTokenSource 取消并行
namespace CancelParallelLoops { using System; using System.Linq; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { int[] nums = Enumerable.Range(0, 10000000).ToArray(); CancellationTokenSource cts = new CancellationTokenSource(); // Use ParallelOptions instance to store the CancellationToken ParallelOptions po = new ParallelOptions(); po.CancellationToken = cts.Token; po.MaxDegreeOfParallelism = System.Environment.ProcessorCount; Console.WriteLine("Press any key to start. Press 'c' to cancel."); Console.ReadKey(); // Run a task so that we can cancel from another thread. Task.Factory.StartNew(() => { if (Console.ReadKey().KeyChar == 'c') cts.Cancel(); Console.WriteLine("press any key to exit"); }); try { Parallel.ForEach(nums, po, (num) => { double d = Math.Sqrt(num); Console.WriteLine("{0} on {1}", d, Thread.CurrentThread.ManagedThreadId); }); } catch (OperationCanceledException e) { Console.WriteLine(e.Message); } finally { cts.Dispose(); } Console.ReadKey(); } } }
IsExceptional 属性(不知道如何使用)
ParallelLoopState 的 IsExceptional 属性为 true ,ShouldExitCurrentIteration等于true。
ShouldExitCurrentIteration 属性
总之,要编写一个健壮的并行循环,必须在并行循环体中检测 ParallelLoopState 对象的 IsExceptional, IsStopped 和 LowestBreakIteration 三个属性,出于简化编程的目的, ParallelLoopState 提供了一个 ShouldExitCurrentIteration 属性,当Stop()\cancel()时,ShouldExitCurrentIteration等于true。
Stop和Break
可以分别用来控制Parallel.For的执行。
Stop表示Parallel.For的执行立刻停止,无论其他执行单元是否达到停止的条件。
Break表示满足条件的当前执行单元立刻停止,而对于其他执行单元,其中满足停止条件也会通过Break停止,其他未满足停止条件的则会继续执行下去,从而全部执行完毕,自然停止。当所有执行单元停止后,Parallel.For函数才停止执行并退出。
执行Stop()LowestBreakIteration为空, LoopState.Break();LowestBreakIteration有值,Stop/Break互斥两个只能有一个执行,Stop停止循环比Break快。
break类似于for的continue,而stop就类似于for的break。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义