第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案。

一. Task的各种返回值-Task<TResult> 

PS: 在前面章节,我们介绍了Task类开启线程、线程等待、线程延续的方式,但我们并没有关注这些方式的返回值,其实他们都是有返回值的Task<TResult>,然后可以通过Task的实例调用Result属性来获取这个返回值。

  下面我们分三类来介绍:

  ①:线程开启类的返回值, 使用Task<TResult>接受,或者直接使用Task接受,通过 实例.Result 来获取返回值。这里的线程开启类有多种,eg: Task.Run()、 task.start()、 Task.Factory.StartNew() 等。

  ②:线程延续类的返回值. eg:ContinueWith。

  ③:线程条件延续类的返回值. eg:WhenAll和WhenAny。

 1. 线程开启类的返回值

1             {
2                 Task<string> task1 = Task.Factory.StartNew(() =>
3                 {
4                     Console.WriteLine("我是子线程哦");
5                     return "ok";
6                 });
7                 task1.Wait();
8                 Console.WriteLine("我是主线程,我要读取子线程task1的返回值为:{0}", task1.Result);
9             }

 

2.  线程延续类的返回值

 

 1             {2                 Task<int> task1 = Task.Run(() =>3                   {4                       Console.WriteLine("我是子线程1哦");5                       return 2;6                   });7 8                 var task2 = task1.ContinueWith((t) =>9                 {
10                     Console.WriteLine("我是子线程2哦");
11 
12                     //这里的t代表 task1
13                     var num = t.Result + 2;
14                     return num.ToString();
15                 });
16 
17                 task2.Wait();
18                 Console.WriteLine("我是主线程,我要读取子线程task1的返回值为:{0}", task1.Result);
19                 Console.WriteLine("我是主线程,我要读取子线程task2的返回值为:{0}", task2.Result);
20             }

 

3. 线程条件延续类

复制代码

 1  {2                 Task<int> task1 = Task.Run(() =>3                 {4                     Console.WriteLine("我是子线程1哦");5                     return 1;6                 });7                 Task<int> task2 = Task.Run(() =>8                 {9                     Console.WriteLine("我是子线程2哦");
10                     return 2;
11                 });
12 
13                 var task = Task.WhenAny(new Task<int>[2] { task1, task2 });
14                 task.Wait();
15 
16                 //下面的值可能是1,也可能是2
17                 Console.WriteLine("我是主线程,我要读取子线程task的返回值为:{0}", task.Result.Result);
18  }

复制代码

 

二. 通用线程异常处理方案

1.  背景:我们想达到一个目的,当同时开启多个线程的时候,其中一个线程报错,不影响其他线程的执行,并且能把错误记下来。

2.   解决方案:多重try-catch,整个外侧主线程一个try-catch,然后线程执行业务再用一个try-catch包裹起来。

常规方式捕获异常:

复制代码

 1             {2                 try3                 {4                     for (int i = 0; i < 5; i++)5                     {6                         string name = string.Format("name{0}", i);7                         var task = Task.Run(() =>8                         {9                             try
10                             {
11                                 //模拟某个线程出错
12                                 if (name == "name2")
13                                 {
14                                     throw new Exception(string.Format("线程执行失败,i={0}", name));
15                                 }
16                                 else
17                                 {
18                                     Console.WriteLine(string.Format("线程执行执行成功,i={0}", name));
19                                 }
20                             }
21                             catch (Exception ex)
22                             {
23                                 Console.WriteLine(ex.Message);
24                             }
25 
26                         });
27                         taskList.Add(task);
28                     }
29                     Task.WaitAll(taskList.ToArray());
30                 }
31                 catch (Exception ex)
32                 {
33                     Console.WriteLine(ex.Message);
34 
35                 }
36             }

复制代码

运行结果:我们发现所有的线程均执行完毕,且name2执行失败,并捕获。

 

补充一下:通过 AggregateException 类来捕获异常。

 

复制代码

 1             {2                 try3                 {4                     for (int i = 0; i < 5; i++)5                     {6                         string name = string.Format("name{0}", i);7                         var task = Task.Run(() =>8                         {9                             throw new Exception(string.Format("线程执行失败,i={0}", name));
10                         });
11                         taskList.Add(task);
12                     }
13                     Task.WaitAll(taskList.ToArray());
14                 }
15                 catch (AggregateException aes)
16                 {
17                     foreach (var item in aes.InnerExceptions)
18                     {
19                         Console.WriteLine(item.Message);
20                     }
21                 }
22             }

复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438249.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)

一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程&#xff1a;所谓的串行编程就是单线程的作用下&#xff0c;按顺序执行。(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程&#xff1a;充分利用多核cpu的优势&#xff0c;同时开启多个线程并行执行。(典型代表…

Mybatis四种分页方式

1.数组分页 查询出全部数据&#xff0c;然后再list中截取需要的部分。 mybatis接口 List<Student> queryStudentsByArray(); xml配置文件 <select id"queryStudentsByArray" resultMap"studentmapper">select * from student</select&…

第十节:利用async和await简化异步编程模式的几种写法

一. async和await简介 PS&#xff1a;简介 1. async和await这两个关键字是为了简化异步编程模型而诞生的&#xff0c;使的异步编程更简洁&#xff0c;它本身并不创建新线程&#xff0c;但在该方法内部开启多线程&#xff0c;则另算。 2. 这两个关键字适用于处理一些文件IO操作。…

第十一节:深究用户模式锁的使用场景(异变结构、互锁、旋转锁)

一. 锁机制的背景介绍 本章节&#xff0c;将结合多线程来介绍锁机制&#xff0c; 那么问题来了&#xff0c;什么是锁呢&#xff1f; 为什么需要锁&#xff1f; 为什么要结合多线程来介绍锁呢&#xff1f;锁的使用场景又是什么呢&#xff1f; DotNet中又有哪些锁呢&#xff1f; …

第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

一. 监视锁(Monitor和lock) 1. Monitor类&#xff0c;限定线程个数的一把锁&#xff08;Synchronized lock是他的语法糖&#xff09;&#xff0c;两个核心方法&#xff1a; Enter&#xff1a;锁住某个资源。 Exit&#xff1a;退出某一个资源。 测试案例&#xff1a;开启5个线…

什么是Mybatis ?

使用JDBC连接数据库 半自动持久层的ORM框架(因为要自己手写sql) 可以使用xml配置,可以使用注解. 优点:1.低耦合,sql重用,编写灵活 2.减少冗余代码 3.兼容数据库 4.能很好的与spring集成 5.提供映射标签,支持对象与数据库的ORM字段映射 缺点:1.sql需要自己编写 2数据库移植性…

第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。

一. 四大并发集合类 背景&#xff1a;我们目前使用的所有集合都是线程不安全的 。 A. ConcurrentBag&#xff1a;就是利用线程槽来分摊Bag中的所有数据&#xff0c;链表的头插法,0代表移除最后一个插入的值. (等价于同步中的List) B. ConcurrentStack&#xff1a;线程安全的St…

#{} 跟${}的区别

#{}是预编译处理 ,可以防止sql注入 ,提高安全性 mybatis 会把sql中的#{}替换成? 调用PreparedStatement set方法赋值 ${}是字符串替换 mybatis会把${}直接替换成变量值

第十五节:深入理解async和await的作用及各种适用场景和用法

一. 同步VS异步 1. 同步 VS 异步 VS 多线程 同步方法&#xff1a;调用时需要等待返回结果&#xff0c;才可以继续往下执行业务 异步方法&#xff1a;调用时无须等待返回结果&#xff0c;可以继续往下执行业务 开启新线程&#xff1a;在主线程之外开启一个新的线程去执行业…

@PostConstruct注解

PostConstruct是Java自己的注解. PostConstruct该注解被用来修饰一个非静态的void()方法. PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次. PostConstruct在构造函数之后执行,init()方法之前执行. 执行顺序 Constructor >> Autow…

springCloud五大组件--Gateway

SpringCloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 Spring Cloud Gateway 的目标&#…

多线程篇(被替换)

一. 背景 在刚接触开发的头几年里&#xff0c;说实话&#xff0c;根本不考虑多线程的这个问题&#xff0c;貌似那时候脑子里也有没有多线程的这个概念&#xff0c;所有的业务都是一个线程来处理&#xff0c;不考虑性能问题&#xff0c;当然也没有考虑多线程操作一条记录存在的并…

springCloud五大组件--Eureka

Spring Cloud 支持了 Zookeeper、Consul 和 Eureka&#xff0c;官方推荐 Eureka。 C(一致性)A(高可用)P(分区容错)理论&#xff0c;Eureka的选择就是放弃C&#xff0c;选择AP。 Eureka 采用纯 Java 实现&#xff0c;除实现了注册中心基本的服务注册和发现之外&#xff0c;极大…

.NET异步程序设计之任务并行库

目录 1.简介2.Parallel类 2.0 Parallel类简介2.1 Parallel.For()2.2 Parallel.ForEach()2.3 Parallel.Invoke()2.4 补充&#xff1a;线程安全集合3.Task类 3.0 Task类简介3.1 创建无返回值的Task任务3.2 创建有返回值的Task任务3.3 为Task添加延续任务3.4 Task.Delay3.5 Task对…

Mysql主从延时解决办法

1.忍受大法 第一种解决办法&#xff0c;很简单&#xff0c;无他&#xff0c;不管他&#xff0c;没有读到也没事。这时业务不需要任何改造&#xff0c;你好&#xff0c;我好&#xff0c;她也好~ 如果业务对于数据一致性要求不高&#xff0c;我们就可以采用这种方案。 2.数据同…

关于C#程序的单元测试

目录 1.单元测试概念2.单元测试的原则3.单元测试简单示例4.单元测试框架特性标签5.单元测试中的断言Assert6.单元测试中验证预期的异常7.单元测试中针对状态的间接测试8.单元测试在MVC模式中的实现8.单元测试相关参考9.示例源代码下载 志铭-2020年1月23日 11:49:41 1.单元测试…

MySql 、Oracle 获取表结构和字段信息

MySql获取表结构信息 SELECTTABLE_NAME,TABLE_COMMENT FROMinformation_schema.TABLES WHERETABLE_SCHEMA dm -- dm 是数据库名称&#xff0c;需替换 ORDER BYTABLE_NAME; MySql获取字段信息 SELECTTABLE_NAME AS tableName,COLUMN_NAME AS columnName,COLUMN_COMMENT AS c…

NuGet是什么?理解与使用(上)

如果你了解python&#xff0c;那么它类似pip。 如果你了解nodejs&#xff0c;那么它类似npm。 如果你了解ruby&#xff0c;那么它类似gem。 对&#xff0c;它就是一个包&#xff08;package&#xff09;管理平台&#xff0c;确切的说是 .net平台的包管理工具&#xff0c;它提…

NuGet是什么?理解与使用(下)

本篇将回答下面几个问题&#xff1a; 如何解读NuGet Gallery上的包信息&#xff1f;如何上传NuGet包到NuGet Gallery&#xff1f;如何安装本地NuGet包&#xff1f;NuGet包的内容文件与目录结构&#xff1f; 如果你没看过上篇那么它在这里&#xff1a; 6号咸鱼&#xff1a;NuG…

C#多线程之旅(1)——介绍和基本概念

阅读目录 一、多线程介绍二、Join 和Sleep三、线程怎样工作四、线程和进程五、线程的使用和误用一、多线程介绍 C#通过多线程支持并行执行的代码。一个线程是一个独立执行的路径&#xff0c;可以同时与其他线程一起运行。一个C#客户端程序(Console,WPF,Winows Forms)开始于一个…