博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net进阶系列(15)-异步多线程(线程的特殊处理和深究委托赋值)(被替换)
阅读量:6881 次
发布时间:2019-06-27

本文共 6664 字,大约阅读时间需要 22 分钟。

1. 线程的异常处理

 我们经常会遇到一个场景,开启了多个线程,其中一个线程报错,导致整个程序崩溃。这并不是我们想要的,我需要的结果是,其中一个线程报错,默默的记录下,其它线程正常进行,保证程序整体可以走下来。

  解决方案:给函数体加try-catch,只让报错线程异常,其它线程可以正常进行。

1         private void button7_Click(object sender, EventArgs e) 2         { 3             Stopwatch watch = new Stopwatch(); 4             watch.Start(); 5             Console.WriteLine("----------------- 八.线程的特殊处理  --------------------------"); 6             Console.WriteLine("----------------- button7_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId); 7             try 8             { 9 10                 TaskFactory taskFactory = new TaskFactory();11                 List
taskList = new List
();12 13 #region 01-异常处理14 {15 for (int i = 0; i < 5; i++)16 {17 string name = string.Format("button_Click{0}", i);18 Action
act = t =>19 {20 try21 {22 //模拟报错23 if (t.ToString().Equals("button_Click2"))24 {25 throw new Exception(string.Format("{0} 执行失败", t));26 }27 Console.WriteLine("{0} 执行成功", t);28 }29 catch (Exception ex)30 {31 Console.WriteLine(ex.Message);32 }33 };34 Task task = taskFactory.StartNew(act, name);35 taskList.Add(task);36 }37 //线程等待38 Task.WaitAll(taskList.ToArray());39 }40 #endregion41 44 }45 catch (AggregateException aes)46 {47 foreach (var item in aes.InnerExceptions)48 {49 Console.WriteLine(item.Message);50 }51 }52 catch (Exception ex)53 {54 Console.WriteLine(ex.Message);55 }56 57 watch.Stop();58 Console.WriteLine("----------------- button7_Click 结束 主线程id为:{0} 总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);59 60 }

运行结果:

2.  线程的取消

      线程不能主动取消,只能通过信号量的形式进行检查,接到取消指令后,后续的线程都将取消。

1  { 2                     //Task不能主动取消,只能通过信号量检查的方式 3                     CancellationTokenSource cts = new CancellationTokenSource(); 4                     for (int i = 0; i < 10; i++) 5                     { 6                         string name = string.Format("button_Click{0}", i); 7                         Action act = t => 8                         { 9                             try10                             {11                                 Thread.Sleep(2000);12                                 //模拟报错13                                 if (t.ToString().Equals("button_Click2"))14                                 {15                                     throw new Exception(string.Format("{0} 执行失败", t));16                                 }17                                 if (cts.IsCancellationRequested)18                                 {19                                     Console.WriteLine("{0} 放弃执行", t);20                                 }21                                 else22                                 {23                                     Console.WriteLine("{0} 执行成功", t);24                                 }25                             }26                             catch (Exception ex)27                             {28                                 cts.Cancel();    //凡是在 button_Click2 的执行线程后执行的,均被放弃了执行29                                 Console.WriteLine(ex.Message);30                             }31                         };32                         Task task = taskFactory.StartNew(act, name, cts.Token);33                         taskList.Add(task);34                     }35                     //线程等待36                     Task.WaitAll(taskList.ToArray());37                 }

运行结果:

 

3.  多线程临时变量

1  { 2                     for (int i = 0; i < 5; i++) 3                     { 4                         int k = i; 5                         Action act = () => 6                         { 7                             Console.WriteLine(k);   //0,1,2,3,4  不一定按照顺序 8                             Console.WriteLine(i);   //全为5 9                         };10                         act.BeginInvoke(null, null);11                     }12 }

4. 线程安全

 当多个线程同时操控一个全局变量时,需要加锁,来保证线程安全。其中锁变量为 私有的静态object变量。eg: private static object btnThreadCore_Click_Lock = new object();

1                 { 2                     for (int i = 0; i < 10000; i++) 3                     { 4                         Task task = taskFactory.StartNew(() => 5                         { 6                             //只有方法外的变量需要加锁 7                             int k = 2; 8                             lock (btnThreadCore_Click_Lock) 9                             {10                                 this.TotalCount += 1;11                             }12                         });13                         taskList.Add(task);14                     }15                     //线程等待16                     Task.WaitAll(taskList.ToArray());17                     //测试输出结果18                     Console.WriteLine(this.TotalCount);   //当不加线程锁的时候,结果不一定是10000,加锁后,一定为1000019                 }

5. 委托的几种赋值形式

      三个方法:TestThread()、TestThread2(string name)、TestThread(string name,string pwd)。

      形式一:声明的委托参数和要赋值的函数参数意义对应

      eg:    Action act1=TestThread ;

                  Action<string> act2=TestThread2;

                  Action<string,string> act3=TestThread3;

注意:这种形式,需要在委托被调用的时候将函数所需的参数值传递进去。

      形式二: 声明无参数委托,但利用()=>进行将有参数的函数转换,可以直接将参数所需的值传递进去,委托调用的时候,将不需要再传递了。

      eg:    Action act1=TestThread ;

                  Action act2=()=>TestThread2("测试参数1");

                  Action act3=()=>TestThread3("测试参数1","测试参数2");

 注意:这种形式,实际上就是直接将函数体赋值给委托,但又把一个函数当做内容传递到了这个函数体内,实际上

            Action act2=()=>TestThread2("测试参数1");   等价于

            Action act2=()=>{

            TestThread2("测试参数1");

           }。

       形式三: 直接将函数体赋值给委托,然后函数体中的内容为一个新的函数,这种形式,需要在委托被调用的时候将函数所需的参数值传递进去。

eg:           Action act1=TestThread ;

                  Action act2=t=>TestThread2(t);

                  Action act3=(m,n)=>TestThread3(m,n);

 注意:这种形式,实际上就是直接将函数体赋值给委托,但又把一个函数当做内容传递到了这个函数体内,实际上

            Action act2=t=>TestThread2(t);   等价于

            Action act2=(t)=>{

            TestThread2("测试参数1");

           }。

 

转载于:https://www.cnblogs.com/yaopengfei/p/7071515.html

你可能感兴趣的文章
Exchange企业实战技巧(13)配置存储配额与邮箱大小限制
查看>>
《统一沟通-微软-技巧》-19-Lync 2010如何使用智能手机中联系人
查看>>
【虚拟化实战】存储设计之三MultiPathing
查看>>
书摘—职场不逃跑
查看>>
新书发布《大数据时代的IT架构设计》
查看>>
《介绍一款开源的类Excel电子表格软件》续:七牛云存储实战(C#)
查看>>
如今的淘宝为什么越来越难做?几个事实摆在我们面前
查看>>
云在天之南——我的七天七夜(初识丽江)
查看>>
再谈PHP从入门到精通需要几年
查看>>
动软.NET系统框架发布免费版本
查看>>
python 学习笔记 表达式(9)
查看>>
pku 1328 第一周训练 ——贪心
查看>>
Android应用资源---绘制资源类型(Drawable)(六)
查看>>
zoj 4777 Watashi's BG DFS解决01背包
查看>>
Outlook.com Rename 杂记...
查看>>
一直以来伴随我的一些学习习惯(三):阅读方法(转载)
查看>>
Directx11教程(57) 环境映射
查看>>
Smark.Data 灵活的查询描述
查看>>
查看Linux 环境系统、CPU位数
查看>>
hudson 邮件信息优化
查看>>