并行编程_Parallel
一、Parallel.Invoke执行多个方法
没有特定执行顺序,利用cpu多核并发执行,在运行并行方法前都会产生一些额外的开销,我们一定要测量运行结果相比没有并行是否有优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #region Parallel.Invoke Stopwatch watch = new Stopwatch(); watch.Start(); Parallel.Invoke(Pinvoke1, Pinvoke2); watch.Stop(); Console.WriteLine( "Parallel run " + watch.ElapsedMilliseconds + " ms" ); watch.Reset(); watch.Start(); Pinvoke1(); Pinvoke2(); watch.Stop(); Console.WriteLine( "Normal run " + watch.ElapsedMilliseconds + " ms" ); Console.ReadKey(); #endregion Parallel.Invoke |
1 2 3 4 5 6 7 8 9 10 11 | private static void Pinvoke1() { Thread.Sleep(3000); Console.WriteLine( "Pinvoke1 ThreadId=" +Thread.CurrentContext.ContextID); } private static void Pinvoke2() { Thread.Sleep(2000); Console.WriteLine( "Pinvoke2 ThreadId=" + Thread.CurrentContext.ContextID); } |
结果:
二、Parallel.For 每一次迭代一会当作一个任务交给一个线程,线程可能会重用,cpu决定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Stopwatch watch = new Stopwatch(); watch.Start(); for ( int i = 0; i < 5; i++) { Console.WriteLine(i); Thread.Sleep(1000); } watch.Stop(); Console.WriteLine(watch.Elapsed); watch.Restart(); Parallel.For(0, 5, i => { Console.WriteLine( "===" + Thread.CurrentThread.ManagedThreadId + "===" ); Console.WriteLine(i); Thread.Sleep(1000); }); watch.Stop(); Console.WriteLine(watch.Elapsed); Console.ReadKey(); |
效果还是非常明显的,但是有个问题是Parallel.For是并行执行,每次迭代基本都会启用新线程,那么我们共用一个全局变量的时候,必须要加锁,出现资源等待,这时用并行就不合适了:示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | object asyncObj = new object (); long value = 0; Stopwatch watch = new Stopwatch(); watch.Start(); for ( int i = 0; i < 9999; i++) { for ( int j = 0; j < 19999; j++) { value++; } } watch.Stop(); Console.WriteLine( "正常运行是" + watch.ElapsedMilliseconds + " ms" ); watch.Restart(); Parallel.For(0, 9999, i => { for ( int j = 0; j < 19999; j++) { lock (asyncObj) { value++; } } }); watch.Stop(); Console.WriteLine( "并行运行是" + watch.ElapsedMilliseconds + " ms" ); Console.ReadKey(); |
三、Parallel.ForEach 都foreach一样,只不过是并行的,也是每次循环一个线程处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | List<Person> list = new List<Person>(); for ( int i = 1; i < 100; i++) { list.Add( new Person { Age = i, Name = "Name" + i }); } Stopwatch watch = new Stopwatch(); watch.Start(); Parallel.ForEach(list, p => { Console.WriteLine( "===" + Thread.CurrentThread.ManagedThreadId + "===" ); Console.WriteLine(p.Name); }); watch.Stop(); Console.ReadKey(); |
四、并行中断
ParallelLoopState:
1、Break-并行循环执行了当前迭代后尽快地停止执行。
//更改方法stop下面的示例,运行结果不一定哦,49,50都出现了
2、Stop-直接停止
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //结果是50 List<Person> list= new List<Person>(); Parallel.For(0, 100, (num, state) => { if (num<50) { list.Add( new Person() {Age = num}); } else { state.Stop(); } }); Console.WriteLine(list.Count); |
五、异常处理
并行执行的时候使用AggregateException获取全部异常,用Exception只能获取其中一个;
1 2 3 4 5 6 7 8 9 10 11 | try { Parallel.Invoke(Pinvoke1, Pinvoke2); } catch (AggregateException aggregateException) { foreach ( var innerException in aggregateException.InnerExceptions) { Console.WriteLine(innerException.Message); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | private static void Pinvoke1() { Thread.Sleep(3000); Console.WriteLine( "Pinvoke1 ThreadId=" + Thread.CurrentContext.ContextID); throw new Exception( "并行任务1抛出异常" ); } private static void Pinvoke2() { Thread.Sleep(2000); Console.WriteLine( "Pinvoke2 ThreadId=" + Thread.CurrentContext.ContextID); throw new Exception( "并行任务2抛出异常" ); } |
六、并行Linq (AsParallel,可以应用任何集合,提高处理速度)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Stopwatch watch= new Stopwatch(); List<Person> list = new List<Person>(); Parallel.For(0,10000,p => { list.Add( new Person() {Age = p,Name = "name" +p}); //注意并行会出现有空对象的现象;也可以调用Invoke方法,里面写for循环就不会出现空对象 }); Console.WriteLine(list.Count); watch.Start(); Console.WriteLine(list.Count); var persons = list.Where(c=>c!= null &&c.Age>100).ToList(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds); watch.Restart(); var parallelPersons = list.AsParallel().Where(c=> c != null && c.Age>100).ToList(); watch.Stop(); Console.WriteLine(watch.ElapsedMilliseconds); Console.ReadKey(); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步