首页 > 编程语言 >C#并行编程:Parallel类

C#并行编程:Parallel类

时间:2024-07-24 17:51:12浏览次数:19  
标签:Console C# void 编程 static WriteLine action Parallel

说明:

Parallel类中提供了三个静态方法作为结构化并行的基本形式:

  • Parallel.Invoke方法:并行执行一组委托。
  • Parallel.For方法:执行与C# for循环等价的并行方法。
  • Parallel.ForEach方法:执行与C#foreach循环等价的并行方法。

这三个方法都会阻塞线程直到所有工作完成为止。和PLINQ一样,在出现未处理异常之后,其他的工作线程将会在其当前迭代完成之后停止,并将异常包装为AggregateException抛出给调用者。

 

1. 与PLINQ一样,Parallel.*方法是针对计算密集型任务而不是I/O密集型任务进行优化的。

2. 循环是无序的,如果需要顺序,直接使用同步。

3. 如果用到共享变量,要使用线程同步锁。

4. 如果虽是大量,但简单无等待的操作,同步执行可能更快。

5. 如果是带数据库操作,请使用事务,注意错误处理。

6. ForEach 比For效率更高。

 

一: Parallel.Invoke:并行执行一组Action委托,然后等待它们完成(尽可能的同时执行)。

    1. 该方法最简单的定义方式如下:public static void Invoke (params Action[] actions);

    2. 如果任务不超过10个,建议直接用Task,因为不超过10个的时候,Invoke内部会使用Task.Factory.StartNew创建任务。直接用Task.Factory.StartNew或者Task.Run效率更高。

    3. 适合用于执行大量且无返回值的场景:如果将一百万个委托传递给Parallel.Invoke方法,它仍然能够有效工作。这是因为该方法会将大量的元素划分为若干批次(自动分批处理),并将其分派给底层的Task。

 1  #region 第一种模式
 2         static void ParallelInvoke1()
 3         {
 4             Parallel.Invoke(Fun1, Fun2);
 5         }
 6         static void Fun1()
 7         {
 8             Console.WriteLine("Fun1");
 9         }
10         static void Fun2()
11         {
12             Console.WriteLine("Fun2");
13         }
14         #endregion
15         #region 第二种模式
16         static void ParallelInvoke2()
17         {
18             Action action = () =>
19              {
20                  Console.WriteLine($"Thread Id:{Thread.CurrentThread.ManagedThreadId }");
21              };
22             Parallel.Invoke(action, action, action, action, action, action, action, action, action, action, action, action);
23             Console.WriteLine("Parallel.Invoke 执行完成");
24         }
25         #endregion
Parallel.Invoke

 

二. Parallel.For使用(无序的),适合带索引的大量循环操作

// 顺序
for(int i=0; i<100; i++)
    Foo(i);
 
// 并行话代码
Parallel.For(0, 100, i=> Foo(i));
// 简洁写法
Parallel.For(0, 100,Foo);
View Code

 

Parallel Options选项配置,有三个属性
1. Cancellation Token 取消任务,并且处理任务被取消后的一些操作
2. MaxDegreeOfParallelism 设置最大并发数,默认-1
3. TaskScheduler指定任务调度器。


ParallelLoopResult 并发结果,有两个属性
1. IsCompleted 任务是否执行完成。
2. LowestBreakIteration 调用Break方法的最小任务索引(小于这个的索引都要执行)


ParallelLoopState,由于并行的For或ForEach的循环体是一个委托,因此无法使用break语句提前结束循环。但是可以调用ParallelLoopState对象的Break方法或Stop方法来跳出或者结束循环
Break
Stop

 1 /// <summary>
 2         /// Parallel.For使用
 3         /// </summary>
 4         /// <param name="num"></param>
 5         static void ParallelForFun(int num)
 6         {
 7             Console.WriteLine($"ParallelFor执行总次数:{num}");
 8             var list = new List<dynamic>() ;
 9             ParallelLoopResult result = Parallel.For(0, num, i =>
10             {
11                 list.Add(new Product { Id = i, nameof = "Testname" });
12                 Console.WriteLine($"Task ID:{Task.CurrentId},Thread:{Thread.CurrentThread.ManagedThreadId }");
13                 Thread.Sleep(20);
14             });
15         }
View Code

a. 循环中断:Parallel.For带ParallelLoopState(执行状态,可以中途取消),带ParallelLoopResult(执行结果)

 1  static void ParallelForAsyncAbort()
 2         {
 3 
 4             ParallelLoopResult result =
 5                 Parallel.For(10, 100, async (int index, ParallelLoopState pls) =>
 6                   {
 7                       Console.WriteLine($"Index:{index} task:{Task.CurrentId},Thread:{Thread.CurrentThread.ManagedThreadId }");
 8                       await Task.Delay(10);
 9                       if (index > 30)
10                           pls.Break();
11                   });
12             Console.WriteLine($"Is completed:{result.IsCompleted} LowestBreakIteration:{result.LowestBreakIteration }");
13         }
View Code

Break:不立马结束循环,而是等所有小于ParallelLoopResult.LowestBreakIteration 的迭代执行完,才结束循环。(用Break时,记得要用大于的条件判断)

Stop:不用等,可以更快捷的结束循环。
Break与Stop都不能停止已经开始的迭代,只可以防止新的迭代开始。

b.循环取消:

 1 static void ParallelForCancel()
 2         {
 3 
 4             var cts = new CancellationTokenSource();
 5             cts.Token.Register(() => { Console.WriteLine($"*** token canceled"); });
 6             cts.CancelAfter(500);//执行500毫秒后取消
 7             try
 8             {
 9                 ParallelLoopResult result = Parallel.For(0, 100, new ParallelOptions()
10                 {
11                     CancellationToken = cts.Token,
12                 }, x =>
13                  {
14                      Console.WriteLine($"loop {x} started");
15                      int sum = 0;
16                      for (int i = 0; i < 100; i++)
17                      {
18                          Thread.Sleep(2);
19                          sum += 1;
20                      }
21                      Console.WriteLine($"loop {x} finished");
22                  });
23             }
24             catch (OperationCanceledException ex)
25             {
26                 Console.WriteLine(ex.Message);
27             }
28         }
循环500毫秒后取消

执行结果,可以看出,取消后,已经开始的任务,还是会继续执行完成

 

三:Parallel.ForEach(大数据集的循环执行,例如:数组,集合,枚举)

 1  // 执行结果是无序的
 2         static void ParallelForEach1()
 3         {
 4             string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
 5             ParallelLoopResult result = Parallel.ForEach(data, a =>
 6                  {
 7                      Console.WriteLine(a);
 8                      
 9                  });
10            
11         }
12         static void ParallelForEach2()
13         {
14             string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight","nine","ten" };
15 
16             ParallelLoopResult result = Parallel.ForEach<string>(data,(str,psl,index)=>
17             {
18                 Console.WriteLine($"str:{str} index:{index}");
19 
20             });
21 
22         }
ParallelForEach

结果是无序的

 

标签:Console,C#,void,编程,static,WriteLine,action,Parallel
From: https://www.cnblogs.com/apple-hu/p/18321407

相关文章

  • Kmesh v0.4发布!迈向大规模 Sidecarless 服务网格
    本文分享自华为云社区《Kmeshv0.4发布!迈向大规模Sidecarless服务网格》,作者:云容器大未来。近日Kmesh发布了v0.4.0版本,感谢社区的贡献者在两个多月的时间里做出了巨大的努力,使得Kmesh取得功能完整度、稳定性、可靠性的多重提升。当前Kmesh相较业界其他方案已经具备显......
  • 2个月搞定计算机二级C语言——真题(1)解析
    1.前言大家好,我是梁国庆。这段时间将持续发布计算机二级C语言真题的解析,想要同步练习,需要资源包的朋友可以跳转免费获取——《3个月搞定计算机二级C语言——准备工作》。现在恐怕要改为2个月搞定计算机二级C语言了,不过没有关系,干就完了!本篇博客将解析计算机二级C语言......
  • C. Card Game
    原题链接题解性质:取奇数位置相加,取偶数位置不相加经过若干次实验,可以得到删除第\(i\)个数,对\([1,i-1]\)个数的奇偶性不造成影响因此,我们试着从最末尾开始删(无后效性)如果末尾是负数,不用管如果末尾是正数,如果是奇数位置,直接相加如果末尾是正数,如果是偶数位置,如果......
  • 从excel列表读取图片,上传并匹配--基于03版
    主要思路:1.读取所有图片,先传到服务器本地,用row行编号命名图片名称.2.传到图片服务器,获取图片url3.与excel其它数据行匹配---------------不知为啥首尾两行不进去的分割线------------------------------publicvoidimportExcel(MultipartFilefiles)throwsException......
  • pycharm配置及python环境相关配置
     python虚拟环境不同项目依赖的第三方包的版本可能不一样,这样一个环境就没法同时开发不同的项目,所以需要创建不同的虚拟环境virtualenv用户创建独立的python环境,多个python项目互相独立互不影响安装方法pipinstallvirtualenv创建虚拟环境virtualenvvenv会......
  • ESP32S3之JTAG调试OPENOCD服务启动失败
    OpenOCDserverisnotrunning![OpenOCD]❌Error:libusb_open()failedwithLIBUSB_ERROR_NOT_FOUND[OpenOCD]❌Error:esp_usb_jtag:couldnotfindoropendevice!OpenOCD打开不成功主要是驱动程序不对修复方法使用Zadig,来修改驱动程序降级之后的驱动,是由哪里......
  • .NET Core 核心知识点(四) -- 初会依赖注入
    控制反转、服务定位器、依赖注入  控制反转:使用对象或者服务的时候,不需要自己去创建/new服务,而是在使用的时候直接声明,容器会自动分配一个服务实例。相当于自己用发电机发电使用和利用电网公司的电的区别,自己发电,我需要一台发电机,安装发电机,自己设置电压,频率等等,而使用电......
  • 查看Oracle执行计划以及真实执行计划
    在Oracle数据库中,查看SQL语句的执行计划可以通过以下几种方法:使用AUTOTRACEAUTOTRACE提供一个简单的方法来查看SQL语句的执行计划和统计信息。你可以在SQL*Plus中使用它:启用AUTOTRACE:SETAUTOTRACEON执行你的SQL语句,Oracle会自动显示执行计划和统计信息......
  • 一文说透ConcurrentHashMap及大厂面试题
    23年毕业半年被裁后,一个月斩获大厂offer,“跟着周哥走,offer手里有”。文中有周哥50+场面试总结出的必会面试题。本期说一下ConcurretHashmap及相关知识点的面试题及答案。注:接下来的内容来自本人整理的面试秘籍。点击此处,免费获取面试秘籍jdk1.7中和jdk1.8中ConcurretH......
  • Linux系统安装Cobol语言及IBM大型机模拟软件Hercules
     COBOL(CommonBusiness-OrientedLanguage)起源于50年代中期,是一种面向过程的高级程序设计语言,主要用于商业和数据处理领域。经过不断发展和标准化,已成为国际上应用最广泛的商业编程语言之一,在某red书上还有招聘COBOL程序员去日本的帖子,个人害怕噶腰子所以不推荐。COBOL语言具......