Parallel==Task+waitall(将主线程也利用了起来,改进了Task)
Invoke()
Parallel.Invoke(() => this.DoSomethingLong("btnParallel_Click_0") , () => this.DoSomethingLong("btnParallel_Click_1") , () => this.DoSomethingLong("btnParallel_Click_2") , () => this.DoSomethingLong("btnParallel_Click_3") , () => this.DoSomethingLong("btnParallel_Click_4") , () => this.DoSomethingLong("btnParallel_Click_5"));
For()
1 Parallel.For(0, 5, t => this.DoSomethingLong($"btnParallel_Click_{t}"));
Foreach() (可以利用ParallelOptions设置最大并发数)
1 Parallel.ForEach(new int[] { 1, 2, 3, 4, 5 }, t => this.DoSomethingLong($"btnParallel_Click_{t}"));
1 ParallelOptions option = new ParallelOptions() 2 { 3 MaxDegreeOfParallelism = 3//最大并发数 4 }; 5 Parallel.ForEach(new int[] { 1, 2, 3, 4, 5, 6 }, option, t => 6 { 7 this.DoSomethingLong($"btnParallel_Click_{t}"); 8 });
1 new Action(() => 2 { 3 ParallelOptions option = new ParallelOptions() 4 { 5 MaxDegreeOfParallelism = 3//最大并发数 6 }; 7 Parallel.ForEach(new int[] { 1, 2, 3, 4, 5, 6 }, option, t => 8 { 9 this.DoSomethingLong($"btnParallel_Click_{t}"); 10 }); 11 }).BeginInvoke(null, null);
结束线程 Break和Stop
1 ParallelOptions option = new ParallelOptions() 2 { 3 MaxDegreeOfParallelism = 3//最大并发数 4 }; 5 Parallel.ForEach(new int[] { 1, 2, 3, 4, 5, 6 }, option, (t, state) => 6 { 7 this.DoSomethingLong($"btnParallel_Click_{t}"); 8 //state.Break();//这一次结束 9 //return; 10 11 state.Stop();//整个Parallel结束 12 return; 13 //不能共存 14 });
多线程的异常处理(主线程抓不到子线程的异常)
1 异常被吞掉了,加上waitall才能抓取到异常 2 Task.WaitAll(taskList.ToArray());
(主线程)红色字体处捕获异常,但是异常已经发生(主线程抓不到子线程的异常)且其他的子线程已经执行(亡羊补牢,为时已晚)。所以,最好在子线程处处理异常,加上Task.WaitAll()。
1 try 2 { 3 TaskFactory taskFactory = new TaskFactory(); 4 List<Task> taskList = new List<Task>(); 5 #region 异常处理 6 ////在线程Action加上try catch,日志记录,不抛异常 7 //for (int i = 0; i < 20; i++) 8 //{ 9 // string name = string.Format($"btnThreadCore_Click_{i}"); 10 // Action<object> act = t => 11 // { 12 // try//---------------------------------------------------------------子线程处理异常 13 // { 14 // Thread.Sleep(2000); 15 // if (t.ToString().Equals("btnThreadCore_Click_11")) 16 // { 17 // throw new Exception(string.Format($"{t} 执行失败")); 18 // } 19 // if (t.ToString().Equals("btnThreadCore_Click_12")) 20 // { 21 // throw new Exception(string.Format($"{t} 执行失败")); 22 // } 23 // Console.WriteLine("{0} 执行成功", t); 24 // } 25 // catch (Exception ex) 26 // { 27 // Console.WriteLine(ex.Message); 28 // }//-----------------------------------------------------------------子线程处理异常 29 // }; 30 // taskList.Add(taskFactory.StartNew(act, name)); 31 //} 32 ////异常被吞掉了,加上waitall才能抓取到异常 33 ////Task.WaitAll(taskList.ToArray()); 34 #endregion 35 36 #region 线程取消 37 ////线程间都是通过共有变量:都能访问局部变量/全局变量/数据库的一个值/硬盘文件 38 ////线程不能被外部停止,只能自身停止自身;或者在任务启动前停止,会抛出异常的 39 //CancellationTokenSource cts = new CancellationTokenSource(); 40 //for (int i = 0; i < 40; i++) 41 //{ 42 // string name = string.Format("btnThreadCore_Click{0}", i); 43 // Action<object> act = t => 44 // { 45 // try 46 // { 47 // //if (cts.IsCancellationRequested) 48 // //{ 49 // // Console.WriteLine("{0} 取消一个任务的执行", t); 50 // //} 51 // Thread.Sleep(2000); 52 // if (t.ToString().Equals("btnThreadCore_Click11")) 53 // { 54 // throw new Exception(string.Format("{0} 执行失败", t)); 55 // } 56 // if (t.ToString().Equals("btnThreadCore_Click12")) 57 // { 58 // throw new Exception(string.Format("{0} 执行失败", t)); 59 // } 60 // if (cts.IsCancellationRequested)//检查信号量 61 // { 62 // Console.WriteLine("{0} 放弃执行", t); 63 // } 64 // else 65 // { 66 // Console.WriteLine("{0} 执行成功", t); 67 // } 68 // } 69 // catch (Exception ex) 70 // { 71 // cts.Cancel();//表示修改了信号量 让大家取消执行 72 // Console.WriteLine(ex.Message); 73 // } 74 // }; 75 // taskList.Add(taskFactory.StartNew(act, name, cts.Token));//没有启动的任务 在Cancel后放弃启动 76 //} 77 //Task.WaitAll(taskList.ToArray()); 78 #endregion 79 80 #region 多线程临时变量 81 //for (int i = 0; i < 5; i++) 82 //{ 83 // int k = i; 84 // new Action(() => 85 // { 86 // Thread.Sleep(100); 87 // //Console.WriteLine(i); 88 // Console.WriteLine(k); 89 // }).BeginInvoke(null, null); 90 //} 91 #endregion 92 93 #region 线程安全 lock 94 //共有变量:都能访问局部变量/全局变量/数据库的一个值/硬盘文件 95 for (int i = 0; i < 10000; i++) 96 { 97 int newI = i; 98 taskList.Add(taskFactory.StartNew(() => 99 { 100 lock (btnThreadCore_Click_Lock)//lock后的方法块,任意时刻只有一个线程可以进入 101 {//这里就是单线程 102 this.TotalCount += 1; 103 IntList.Add(newI); 104 } 105 })); 106 } 107 Task.WaitAll(taskList.ToArray()); 108 109 Console.WriteLine(this.TotalCount); 110 Console.WriteLine(IntList.Count()); 111 #endregion 112 } 113 catch (AggregateException aex)//-------------------------------------------主线程捕获异常 114 { 115 foreach (var item in aex.InnerExceptions) 116 { 117 Console.WriteLine(item.Message); 118 } 119 } 120 catch (Exception ex) 121 { 122 Console.WriteLine(ex.Message); 123 }