Parallel 并行编程

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             }
原文地址:https://www.cnblogs.com/anwser-jungle/p/8881655.html