如何使用 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,一经查实,立即删除!

相关文章

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

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

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

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

.NET Core AWS S3云存储

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

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

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

龙芯.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 — 该目录中通常包括系统引导后被挂载的文件系统…

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

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

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

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

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具

利用 C# 中的 FileSystemWatcher 制作一个文件夹监控小工具独立观察员 2020 年 12 月 26 日前一段看到微信公众号 “码农读书” 上发了一篇文章《如何使用 C# 中的 FileSystemWatcher》&#xff08;翻译自&#xff1a;https://www.infoworld.com/article/3185447/how-to-work-w…

u盘安全删除 linux,为什么要安全删除U盘

原标题&#xff1a;为什么要安全删除U盘移除闪存设备时会对电脑造成危害吗&#xff1f;我们为什么要安全的移除它们&#xff1f;历史上&#xff0c;操作系统将磁盘作为信任对象不需要突然改变状态。当读写文件时&#xff0c;操作系统不希望文件在读写的过程中突然消失。如果文件…

如何在 C# 中使用 投影(Projection)

投影(Projection) 是一种可以将查询结果进行 塑性 的一种操作&#xff0c;你可以使用 投影 将一个 object 转成仅包含你需要属性的新对象&#xff0c;这篇文章中&#xff0c;我们就一起看看如何使用 投影 功能。C# 中的投影 LINQ 集成查询中有两个支持投影的扩展方法&#xff0…

Linux语言写的高通滤波,高通滤波器c语言实现

描述高通滤波器&#xff0c;又称低截止滤波器、低阻滤波器&#xff0c;允许高于某一截频的频率通过&#xff0c;而大大衰减较低频率的一种滤波器。它去掉了信号中不必要的低频成分或者说去掉了低频干扰。高通滤波器是一种让某一频率以上的信号分量通过&#xff0c;而对该频率以…

在 WSL Ubuntu 上使用 .NET 进行跨平台开发新手入门

翻译自 haydenb 2020年6月3日的文章《Getting started with cross-platform development using .NET on Ubuntu on WSL》 [1].NET 是一个开源软件框架&#xff0c;用于在 Linux、Windows 和 macOS 上构建跨平台应用程序。WSL 上的 Ubuntu [2]允许您同时为 Ubuntu 和 Windows 构…

明源云·天际,地产⾏业的Salesforce Lightning Platform

源宝导读&#xff1a;2020年11月6日&#xff0c;明源云在CIO峰会上正式对外发布了“天际开放平台”&#xff0c;这是明源云凝聚其20多年行业经验打造的一款企业级PaaS平台。本文将介绍我们对企业级PaaS平台的行业思考&#xff0c;以及为加速泛地产生态链数字化转型而做的技术创…

c程序设计语言选修难吗,欢迎大家选修C语言程序设计这门课,本帖解释一下一些常见的问题...

置顶欢迎大家选修C语言程序设计这门课&#xff0c;本帖解释一下一些常见的问题叶卡林娜发表于2017年01月05日首先欢迎大家选修浙大翁恺老师的C语言程序设计课程。开课2天就看到讨论区已经有这么多帖子&#xff0c;说明同学们的学习热情很高。结合前几次开课的经验以及目前在讨论…

IdentityServer4系列 | 支持数据持久化

一、前言在前面的篇章介绍中&#xff0c;一些基础配置如API资源、客户端资源等数据以及使用过程中发放的令牌等操作数据&#xff0c;我们都是通过将操作数据和配置数据存储在内存中进行实现的&#xff0c;而在实际开发生产中&#xff0c;我们需要考虑如何处理数据持久化呢&…

c语言修仙受控可看吗,强推三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花...

大家好&#xff0c;我是小龙。今天我给大家推荐三本神奇到爆的小说&#xff0c;c语言修仙&#xff0c;程序员与修真会擦出什么火花!一《c语言修仙》【一十四洲】【简介】: 林浔是一个程序员&#xff0c;通宵编代码后发现自己身体内多了一个程序输入窗口。他尝试编了一个循环程序…

【Vue】Vue与ASP.NET Core WebAPI的集成

SPA单页面应用已经遍地开花&#xff0c;熟知的三大框架&#xff0c;Angular、Vue和React&#xff0c;其中Angular与React均可集成至ASP.NET Core&#xff0c;且提供了相关了中间件。但是Vue没有:“As far as I’m aware, we don’t have plans to introduce Vue-specific featu…

引入Jaeger——封装

随着微服务的普及&#xff0c;微服务间的调用全链路跟踪也火了起来&#xff0c;Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目&#xff0c;在.net core中&#xff0c;提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包…