如何使用 C# 在异步代码中处理异常

异常处理是一种处理运行时错误的技术,而 异步编程 允许我们在处理资源密集型的业务逻辑时不需要在 Main 方法或者在 执行线程 中被阻塞,值得注意的是,异步方法和同步方法的异常处理机制是不一样的,本篇我们就来讨论下如何在异步方法中处理异常。

异步方法 VS 同步方法 的异常处理

在同步代码中抛出异常,它会一直以冒泡的方式往上抛,直到遇到可以处理这个异常的 catch 块为止,可以想象,异步方法中的异常抛出肯定要比这个复杂。

大家都知道 异步方法 可以有三种返回类型,如:void, Task, Task<TResult>,当异常方法的返回值是 Task ,Task<TResult> 的方法中抛出异常的话,这个异常对象会被塞到 AggregateException 对象中,然后包裹在 Task 中进行返回,有些朋友可能要问,如果异步方法中抛出了几个异常怎么办?其实也是一样的道理,这些异常对象都会被塞到 AggregateException 中通过 Task 去返回。

最后,如果异常出现在返回值为 void 的异步方法中,异常是在调用这个异步方法的 SynchronizationContext 同步上下文上触发。

返回 void 异步方法中的异常

下面的程序展示了返回 void 的异步方法中抛出了异常。

class Program{static void Main(string[] args){ThisIsATestMethod();Console.ReadLine();}public static void ThisIsATestMethod(){try{AsyncMethodReturningVoid();}catch (Exception ex){Console.WriteLine(ex.Message);}}private static async void AsyncMethodReturningVoid(){await Task.Delay(1000);throw new Exception("This is an error message...");}}

从图中可以看到,AsyncMethodReturningVoid 方法抛出的异常会被包裹此方法的 try catch 捕捉到。

返回 Task 的异步方法异常

当异常从返回值为 Task 的异步方法中抛出,这个异常对象会被包裹在 Task 中并且返回给方法调用方,当你用 await 等待此方法时,只会得到一组异常中的第一个被触发的异常,如果有点懵的话,如下代码所示:

class Program{static void Main(string[] args){ExceptionInAsyncCodeDemo();Console.ReadLine();}public static async Task ExceptionInAsyncCodeDemo(){try{var task1 = Task.Run(() => throw new IndexOutOfRangeException("IndexOutOfRangeException is thrown."));var task2 = Task.Run(() => throw new ArithmeticException("ArithmeticException is thrown."));await Task.WhenAll(task1, task2);}catch (AggregateException ex){Console.WriteLine(ex.Message);}catch (Exception ex){Console.WriteLine(ex.Message);}}}

从上面代码中可以看出 task1 和 task2 都会抛出异常,但在 catch 块中只捕获了 task1 中的异常,这就说明返回值为 Task 的多个异常的方法中,调用方只能截获第一次发生异常的异常对象。

使用 Exceptions 属性 获取所有异常

要想获取已抛出的所有异常,可以利用 Task.Exceptions 属性来获取,下面的代码清单展示了如何在返回 Task 的方法中获取所有的异常信息。

class Program{static void Main(string[] args){ExceptionInAsyncCodeDemo();Console.ReadLine();}public static async Task ExceptionInAsyncCodeDemo(){Task tasks = null;try{var task1 = Task.Run(() => throw new IndexOutOfRangeException("IndexOutOfRangeException is thrown."));var task2 = Task.Run(() => throw new ArithmeticException("ArithmeticException is thrown."));tasks = Task.WhenAll(task1, task2);await tasks;}catch{AggregateException aggregateException = tasks.Exception;foreach (var e in aggregateException.InnerExceptions){Console.WriteLine(e.GetType().ToString());}}}}

使用 AggregateException.Handle 处理所有异常

你可以利用 AggregateException.Handle 属性去处理一组异常中的某一个,同时忽略其他你不关心的异常,下面的代码片段展示了如何去实现。

class Program{static async Task Main(string[] args){await ExceptionInAsyncCodeDemo();Console.Read();}public static async Task ExceptionInAsyncCodeDemo(){Task tasks = null;try{var task1 = Task.Run(() => throw new IndexOutOfRangeException("IndexOutOfRangeException is thrown."));var task2 = Task.Run(() => throw new ArithmeticException("ArithmeticException is thrown."));tasks = Task.WhenAll(task1, task2);await tasks;}catch(AggregateException ex){AggregateException aggregateException = tasks.Exception;foreach (var e in aggregateException.InnerExceptions){Console.WriteLine(e.GetType().ToString());}}}}

上面的代码片段表示:IndexOutOfRangeException 会被处理, InvalidOperationException 会被忽略。

最后想说的是,你可以利用 异步编程 来提高程序的扩展性和吞吐率,当你在使用异步方法时,请注意在异步方法中的异常处理语义和同步方法中的异常处理是不一样的。

译文链接:https://www.infoworld.com/article/3453659/how-to-handle-exceptions-in-asynchronous-code-in-c.html

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

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

相关文章

在oracle中游标的操作,Oracle中的游标和函数详解

Oracle中的游标和函数详解1.游标游标是一种 PL/SQL 控制结构&#xff1b;可以对 SQL 语句的处理进行显示控制&#xff0c;便于对表的行数据逐条进行处理。 游标并不是一个数据库对象&#xff0c;只是存留在内存中。操作步骤&#xff1a;声明游标打开游标取出结果&#xff0c;此…

对 Redis 中的有序集合SortedSet的理解

本篇说一下Redis中的 有序集合类型&#xff0c;曾几何时&#xff0c;我们想把所有数据存到内存中的 数据结构 中&#xff0c;但为了多机器共享内存&#xff0c;不得不将这块内存包装成wcf单独部署&#xff0c;同时还要考虑怎么序列化&#xff0c;烦心事太多太多。。。后来才知道…

php查询类似abab,ABAB中的正则表达式匹配编号(必须相同) - php

我已经搜索了许多答案来匹配ABAB pattern&#xff0c;这些答案与1212或2323的任意字符匹配&#xff0c;已阅读this too但我发现匹配ABAB模式的模式不起作用&#xff0c;它也匹配4444我试图找出模式来匹配以下主题&#xff1a;232345459898但可能不匹配4444或5555&#xff0c;因…

代码质量在「内卷时代」的重要性

这里是Z哥的个人公众号每周五11&#xff1a;45 按时送达当然了&#xff0c;也会时不时加个餐&#xff5e;我的第「173」篇原创敬上大家好&#xff0c;我是Z哥。提到代码质量&#xff0c;不知道你的脑海中浮现出的第一个词是什么&#xff1f;规范&#xff1f;可读性&#xff1f;…

oracle asm 配置失败,Oracle ASMLib安装与配置

什么是ORACLE ASMLib&#xff1f;ASMLib 是一个适用于 Oracle 数据库 的自动存储管理(ASM)功能的支持库。ASM简化了数据库和管理&#xff0c;它不再需要 DBA 直接管理可能数千个的 Oracle 数据库文件&#xff0c;而只需管理分配给 Oracle 数据库的磁盘组。ASMLib 令使用 ASM 的…

.NET Core AWS S3云存储

【导读】最近有需要用到AWS S3云存储上传附件&#xff0c;这里对利用.NET或.NET Core在调用SDK APi需要注意的一点小问题做个记录&#xff0c;或许能对后续有用到的童鞋提供一点帮助Amazon Simple Storage Service (Amazon S3) 是一种对象存储服务&#xff0c;提供行业领先的可…

oracle数据库查看size,[oracle] 查看oracle数据库表空间使用率,定位数据size较大对象...

1.查看表空间使用情况with ts as (SELECT d.tablespace_name "Name", d.status "Status",TO_CHAR (NVL (a.MAXBYTES / 1024 / 1024 /1024, 0), 99,999,990.90) "Maxsize (G)",TO_CHAR (NVL (a.BYTES / 1024 / 1024 /1024, 0), 99,999,990.90) &q…

如何解决在ASP.NET Core中找不到图像时设置默认图像

背景web上如果图片不存在一般是打xx&#xff0c;这时候一般都是会设置默认的图片代替。现在用中间件的方式实现统一设置&#xff0c; 一次设置&#xff0c;全部作用 。此示例演示如何解决在ASP.NET Core中找不到图像时设置默认图像先决条件Visual Studio 2017或更高版本。启用V…

缩减oracle日志,[20180829]减少日志生成量.txt

[20180829]减少日志生成量.txt--//最近一段时间优化一下生产数据库,主要是问题比我预计要严重,实际上exadata实在太快了,把许多问题都给掩盖了.--//实际上这个问题很早就存在,我实在不想提,基于国内许多应用都可能存在类似问题,还是写一下.SQL ordered by Executions%CPU - CPU…

ACM中算法时间约束

ACM中算法时间约束 一般ACM竞赛C/C的时间限制是一秒&#xff0c;因此可以根据题目数据来推断该题所使用的算法。 算法的时间复杂度在 1 0 7 10^7 107左右合适&#xff0c;最多不能超过 1 0 8 10^8 108&#xff0c; O ( n ) O(n) O(n)的极限就在 1 0 8 10^8 108左右。 问题规…

MiniProfiler,一个.NET简单但有效的微型分析器

背景MVC MiniProfiler是Stack Overflow团队设计的一款对ASP.NET MVC的性能分析的小程序。可以对一个页面本身&#xff0c;及该页面通过直接引用、Ajax、Iframe形式访问的其它页面进行监控,监控内容包括数据库内容&#xff0c;并可以显示数据库访问的SQL&#xff08;支持EF、EF …

oracle类似isempty,NULLs和empty strings在不同数据库的中特点

1.以oracle为例SQL> create table test(id int primary key,content varchar(20));SQL> INSERT INTO test (id, content) VALUES (1, NULL);SQL> INSERT INTO test (id, content) VALUES (2, );SQL> INSERT INTO test (id, content) VALUES (3, );SQL> INSERT …

龙芯.NET正式发布 稳步推进生态建设

2020年12月19日&#xff0c;2020中国. NET开发者大会于苏州开幕。此次大会上&#xff0c;龙芯发布了龙芯.NET 3。龙芯.NET 3基于.NET Core 3.1&#xff0c;支持该版本具备的所有主要功能&#xff0c;包括GC、AOT等。CoreCLR、CoreFX、ASP.NET Core等库的测试通过情况与x64/arm6…

有温度的技术,改善上亿人的生活

06有温度的技术&#xff0c;改善上亿人的生活鱼小皮哥&#xff0c;现在的 APP 真是越来越难用了&#xff0c;功能多、操作复杂、广告更多。唉&#xff0c;可不是么&#xff0c;而且人们的生活已经离不开 APP 了&#xff01;老百鱼小皮我爷爷最近的视力下降的很快&#xff0c;用…

Linux链接文件包括,Linux操作系统——系统各目录有什么作用、以及文件链接过程...

三、 Linux 系统目录结构/bin — 用来贮存用户命令。目录 /usr/bin 也被用来贮存用户命令。/sbin — 许多系统命令(例如 shutdown)的贮存位置。目录 /usr/sbin 中也包括了许多系统命令。/root — 根用户(超级用户)的主目录。/mnt — 该目录中通常包括系统引导后被挂载的文件系统…

linux脚本传参修改配置文件,shell脚本修改配置文件指定行的值

配置文件内容为Version1ExpireTime300MaxProcessTime15MaxQueueSize2000MaxStatisticsTime1000000StatisticsCount10根据关键字MaxStatisticsTime获取行号,修改对应的value值change_file.sh#!/bin/bashfile_name"config.xml"key_value"MaxStatisticsTime"c…

刚转Java?那准备转回.NET5吧!

再过几天就2021年了&#xff0c;回首今年最大的变化就是.NET5的发布&#xff0c;终结了.NET Framework和.NET Core两个分支。虽然因为新冠疫情原因&#xff0c;原定于.NET5的部分功能被推迟到.NET6了&#xff0c;但.NET5是一个非常非常重要的版本&#xff0c;会载入史册的一个版…

azure linux 多磁盘 lvm,EVE-NG扩展磁盘空间(扩展LVM卷)

环境准备系统环境&#xff1a;EVE-PRO-VM-2.0.4-20前期是使用ova导入安装&#xff0c;精简置备&#xff0c;40G虚拟磁盘容量。空间不足&#xff0c;尝试了很久&#xff0c;记录操作记录如下&#xff1a;血泪教训&#xff1a;操作不当有可能引起数据丢失&#xff0c;需要提前备份…

在 xunit 测试项目中使用依赖注入

在 xunit 测试项目中使用依赖注入Intro之前写过几篇 xunit 依赖注入的文章&#xff0c;今天这篇文章将结合我在 .NET Conf 上的分享&#xff0c;更加系统的分享一下在测试中的应用案例。之所以想分享这个话题是因为我觉得在我们开发过程中测试是非常重要的一部分&#xff0c;高…

linux 端口qos,linux的qos机制 - cgroup篇 (2)

这篇重点讲述cgroup如何控制blkio子系统的qos&#xff0c;首先看下设置blkio.weight blkio.weight_device我的理解是blkio.weight是整个io子系统的权重值&#xff0c;而blkio.weight_device是针对特定的major:minor 设备的权重blkio.throttle.read_bps_device blkio.throttle.w…