专栏首页黄腾霄的博客2018-9-24-请不要依赖于异步代码的调用方catch异常

2018-9-24-请不要依赖于异步代码的调用方catch异常

熟悉了c#的异步方法后,各种是不是就会有一种一发不可收拾的情况


对于我们熟悉的 async/await 方法,我们知道await可以执行一个异步方法,并且在方法结束后“继续”当前方法之后的代码。 这个对于执行耗时操作,且不阻塞当前线程的情形非常有效,例如

foo()
{
    await A_async();
    B();
}

那么假设下如果方法A_async会抛出异常,那怎么办。

很简单用trycatch,可以很好处理这些异常

foo()
{
    try
    {
        await A_async();
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
    }
    B();
}

但是如果期望是在外部catch异常会如何?

foo()
{
    await A_async();
    B();
}

foo2()
{
    try
    {
        foo();
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
    }
}

答案是无法catch。

虽然A_async()的异常是在foo方法内部抛出,但是在遇到await关键字时,foo2的线程就开始“分叉”成2个线程执行。所以可以认为,foo2的线程已经完成的他的try代码块

那么第二个问题,如果现在是方法B会抛出异常,而A_async不会,那么下面两种写法那种会被catch?

foo()
{
    await A_async().ConfigureAwaiter(True);
    B();
}

foo2()
{
    try
    {
        foo();
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
    }
}
foo()
{
    await A_async().ConfigureAwaiter(False);
    B();
}

foo2()
{
    try
    {
        foo();
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
    }
}

铛铛,都不会被catch。不管B是否在同步上下文执行,外层的catch代码都不会进行等待。

但是以下情况就会被catch咯

foo()
{
    B();
    await A_async().ConfigureAwaiter(False);
}

foo2()
{
    try
    {
        foo();
    }
    catch(Exception e)
    {
        Console.WriteLine(e);
    }
}

因为代码在遇到await 关键字之前,实际还在trycatch语句块之中。


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E8%AF%B7%E4%B8%8D%E8%A6%81%E4%BE%9D%E8%B5%96%E4%BA%8E%E5%BC%82%E6%AD%A5%E4%BB%A3%E7%A0%81%E7%9A%84%E8%B0%83%E7%94%A8%E6%96%B9catch%E5%BC%82%E5%B8%B8.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何避免写出await await

    小伙伴们应该对C#中的await/async模式都很熟悉了,对于一个Task或者Task<T>对象,使用await进行异步任务的等待

    黄腾霄
  • 2020-6-8-理解node中的stream的背压机制

    使用合适的压缩算法能够有效减少请求文件的大小,从而减少网络中的数据传输量,提升响应速度。

    黄腾霄
  • 2019-5-17-反模式之Continuous Obsolescence

    Obsolescence是过时,弃用的意思。Continuous Obsolescence来自于软件技术的持续更新。有人说技术持续更新不是很好的事情么?但是持续...

    黄腾霄
  • Nuance宣布与ROOBO战略合作,共同布局智能机器人市场

    【新智元导读】Nuance美国昨日官方宣布与中国人工智能机器人系统公司ROOBO达成战略合作,将其作为全球AI、Robotics以及IOT领域的服务集成商和发行...

    新智元
  • 【从零学习OpenCV 4】中值滤波

    中值滤波就是用滤波器范围内所有像素值的中值来替代滤波器中心位置像素值的滤波方法,是一种基于排序统计理论的能够有效抑制噪声的非线性信号处理方法。中值滤波计算方式如...

    小白学视觉
  • Aliyun WinServer离线迁移到腾讯云

    在桌面输入快捷键win+r打开运行窗口,然后输入 diskmgmt.msc,按 Enter,打开 “磁盘管理”。

    jonnyzhao
  • MySQL Galera Cluster全解析 Part 8 Galera Cluster和传统MySQL的不同点

    MySQL Galera Clusters全解析 Part 1 Galera Cluster 简介

    bsbforever
  • Entity Framework Code First 支持存储过程

    存储过程(Stored Procedure)不仅仅是将多得简直荒唐的业务逻辑塞入数据库的一种方式;它还是避免将多得简直荒唐的存储逻辑塞入应用程序层(applic...

    张善友
  • maven常用命令

    mvn deploy:deploy-file -DgroupId=组名 -DartifactId=唯一标识 -Dversion=版本号 -Dpackaging=...

    用户2603479
  • 详解图像滤波原理及实现!

    图像的实质是一种二维信号,滤波是信号处理中的一个重要概念。在图像处理中,滤波是一常见的技术,它们的原理非常简单,但是其思想却十分值得借鉴,滤波是很多图像算法的前...

    Datawhale

扫码关注云+社区

领取腾讯云代金券