当前位置: 首页 > news >正文

1.15 并行编程

1.并行循环基本语法

2.并行循环原理

3.并行循环中的异常处理

4.停止

5.中断


1.并行循环基本语法

C#中的Parallel类(位于 System.Threading.Tasks 命名空间).NET提供的并行编程核心工具,旨在简化"数据并行""任务并行"开发,充分利用多核CPU资源,避免手动管理线程的复杂度;它的核心目标是将串行执行的任务(如循环、独立方 法)"自动拆分为多个并行任务, 复用线程池线程执行",提升CPU密集型任务的效率
1).Parallel.For:并行版for循环 替代传统的串行for循环,将循环迭代拆分为多个并行任务执行,适合"遍历连续整数范围"的场景

usingSystem;usingSystem.Threading.Tasks;classParallelForDemo{staticvoidMain(){int[]data=newint[10000];// 初始化数组(串行)for(inti=0;i<data.Length;i++)data[i]=i;// 并行遍历数组,每个元素乘以2(CPU密集型)Parallel.For(0,data.Length,i=>{data[i]*=2;// 打印线程ID,验证并行(不同迭代可能在不同线程执行)if(i%1000==0)Console.WriteLine($"迭代{i},线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId}");});Console.WriteLine($"第一个元素:{data[0]}, 最后一个元素:{data[9999]}");}}

2).Parallel.Foreach:并行版foreach替代传统的串行foreach,遍历实现了IEnumerable的集合(如 List、数组、Dictionary),适合"遍历非连续集合"的场景
usingSystem;usingSystem.Collections.Generic;usingSystem.Threading.Tasks;classParallelForEachDemo{staticvoidMain(){List<string>fruits=newList<string>{"Apple","Banana","Orange","Grape","Mango"};// 并行遍历集合,处理每个元素Parallel.ForEach(fruits,fruit=>{stringupperFruit=fruit.ToUpper();Console.WriteLine($"处理结果:{upperFruit}(线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId})");});}}

3).Parallel.Invoke:并行执行多个独立的任务 用于一次性执行多个无返回值、无参数的独立方法,适合"多任务并行执行"场景
usingSystem;usingSystem.Threading.Tasks;classParallelDemo{staticvoidMain(){// 并行执行两个独立方法,无需关注执行顺序Parallel.Invoke(()=>CalculateSum(1,1000000),// 任务1:计算1到100万的和()=>PrintMessage("Hello Parallel")// 任务2:打印信息);Console.WriteLine("所有并行任务执行完成");}staticvoidCalculateSum(intstart,intend){longsum=0;for(inti=start;i<=end;i++)sum+=i;Console.WriteLine($"Sum:{sum}(线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId})");}staticvoidPrintMessage(stringmsg){Console.WriteLine($"{msg}(线程ID:{System.Threading.Thread.CurrentThread.ManagedThreadId})");}}

2.并行循环原理

并行循环的原理是"分块减少调度开销""线程复用避免创建成本"a.数据分区(分块)—— 不是"均分",而是"动态按需分块"并行循环首先会将待处理的数据集(比如0~999的迭代、List集合)拆分为若干"分区(Chunk)",但不是静态均分,而是由.NET 的"分区器(Partitioner)"动态调整-静态分区(适用于迭代执行时间均匀的场景)启动前将数据均分(比如1000个迭代,4核CPU拆成4,每块250),优点是分区开销小,缺点是如果某块迭代执行慢(比如 处理大数据),会导致"有的线程闲、有的线程忙"(负载不均)-动态分区(Parallel默认策略)不提前均分,而是"按需分配小批次"(比如每次分配10~20个迭代为一个小块),线程处理完当前小块后,立刻去"领取"下一 个小块,直到所有数据处理完 ✅优势:解决负载不均问题(比如某块迭代执行慢,其他线程不会等,继续领新块),最大化CPU利用率 b.线程调度 —— 复用线程池,而非创建新线程 Parallel循环不会为每个块创建新线程,而是复用.NET"线程池(ThreadPool)"的工作线程 线程池默认有"最小线程数(= CPU 核心数)""最大线程数(默认 1023)",Parallel会向线程池请求线程,而非手动创建(避 免线程创建/销毁的昂贵开销)并行度(同时运行的线程数)默认由".NET根据CPU核心数、当前系统负载动态调整"c.执行与线程复用 —— 一个线程处理多个块 线程与块不是一一绑定,一个线程处理完一个小块后,不会销毁,而是立刻从分区器领取下一个小块继续执行;直到所有小块 处理完毕,线程才会回到线程池,等待后续复用 d.收尾 —— 合并结果(如有)+处理异常-若有共享结果(比如累加求和),需通过原子操作/-若多个块抛出异常,会封装为AggregateException统一抛出

3.并行循环中的异常处理

并行循环中的异常不会立即停止本次迭代,而是停止新的迭代;trycatch放在并行循环的外面
usingSystem;usingSystem.Threading.Tasks;classParallelExceptionBasic{staticvoidMain(){try{// 并行循环:迭代1和3抛出不同异常Parallel.For(0,5,i=>{Console.WriteLine($"迭代{i}开始执行");if(i==1)thrownewArgumentException($"参数非法:迭代{i}");// 业务异常1if(i==3)thrownewDivideByZeroException($"除零错误:迭代{i}");// 业务异常2Thread.Sleep(100);// 模拟业务逻辑});}// 必须捕获AggregateException,而非单个异常catch(AggregateExceptionaggregateEx){Console.WriteLine($"捕获到{aggregateEx.InnerExceptions.Count}个异常:");// 遍历所有内部异常,逐个处理foreach(varinnerExinaggregateEx.InnerExceptions){// 区分异常类型,针对性处理switch(innerEx){caseArgumentExceptionargEx:Console.WriteLine($"参数异常:{argEx.Message}");break;caseDivideByZeroExceptiondivEx:Console.WriteLine($"除零异常:{divEx.Message}");break;default:Console.WriteLine($"未知异常:{innerEx.Message}");break;}}}// 可选:捕获其他非并行循环的异常(比如参数错误)catch(Exceptionex){Console.WriteLine($"非聚合异常:{ex.Message}");}}}

4.停止

Stop是"紧急停止"—— 不管索引顺序,新迭代全不调度,已开始的迭代也建议尽快退出(而非执行完)
usingSystem;usingSystem.Threading.Tasks;classParallelBreakVsStop{staticvoidMain(){Console.WriteLine("=== 测试 Stop() ===");varresult=Parallel.For(0,10,(i,state)=>{Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 迭代{i}开始执行");if(i==5){Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 触发 Stop()");state.Stop();}// 关键:检查IsStopped,尽快退出(Stop的核心)if(state.IsStopped){Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 迭代{i}检测到Stop,立即退出");return;// 不执行后续的500ms延迟}// 若没检测IsStopped,才会执行完500ms(这是你觉得没区别的常见原因)Task.Delay(500).Wait();Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 迭代{i}执行完成");});Console.WriteLine($"循环是否完成:{result.IsCompleted}");Console.WriteLine($"最低中断迭代索引:{result.LowestBreakIteration??-1}\n");}}


5.中断

Break是"有序中断"—— 保证中断点前的迭代全执行完,只停后面的
usingSystem;usingSystem.Threading.Tasks;classParallelBreakVsStop{staticvoidMain(){Console.WriteLine("=== 测试 Break() ===");varresult=Parallel.For(0,10,(i,state)=>{Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 迭代{i}开始执行");if(i==5){Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 触发 Break()");state.Break();}// 模拟耗时500ms的业务逻辑(Break下会执行完)Task.Delay(500).Wait();Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 迭代{i}执行完成");});Console.WriteLine($"循环是否完成:{result.IsCompleted}");Console.WriteLine($"最低中断迭代索引:{result.LowestBreakIteration}\n");}}

http://www.cnnetsun.cn/news/94950.html

相关文章:

  • Swagger2Word终极指南:一键将API文档转为专业Word格式
  • 【C2000中断Debug】如何定位与调试异常中断
  • vue3中computed计算属性和方法的区别
  • LobeChat国际社区动态:全球开发者共同维护
  • 基于STM32的水质检测系统设计与实现
  • Radm1n1ster CN
  • 重构智慧书-第18条:实力与实干
  • 读捍卫隐私08智能出行
  • 媒体专访实录:LobeChat创始人谈开源初心
  • 小喵播放器 1.1.2| 一款支持视频超分的播放器,支持网页视频以及B站番剧
  • LobeChat待办事项提取与提醒功能实现
  • LobeChat会话管理机制揭秘:让每一次对话都井然有序
  • JS利用分片技术实现大文件分块上传的性能优化?
  • HTML5配合AES加密实现大文件分块传输安全?
  • NPP 热带森林:墨西哥查梅拉,1982-1995 年,R1
  • WordPress粘贴微信公众号内容自动排版
  • 毕设 stm32与深度学习口罩佩戴检测系统(源码+硬件+论文)
  • 手机端AIDE安卓音乐播放器软件代码
  • 如何在 Windows 11/10 中启用IE浏览器?恢复 Internet Explorer 一键搞定,就这么简单!
  • Scholar Inbox 订阅最新学术进展至邮箱
  • D.二分查找-二分答案-求最小——1283. 使结果不超过阈值的最小除数
  • A.每日一题——3562. 折扣价交易股票的最大利润
  • 圣默思 Teledyne DalsaFilr SWIR相机
  • Go 语言结构
  • JavaScript for 循环详解
  • 5步搞定SillyTavern版本升级:告别烦恼的完整指南
  • 猫头虎AI开源分享:如何批量获取稀土掘金社区文章阅读量暨文章阅读量数据批量提取解决方案
  • DBO-RBF多变量回归预测 优化宽度+中心值+连接权值 (多输入单输出)Matlab代码
  • 亲测!WordPress网站接入聚合登录实践
  • 15、Mozilla模板系统:功能、构建与应用实践