C# 中try catch finally之异步中注意事项(二)

本文由 CodeMotion原创,转载请声明。

一.前言


上一篇,我们观察了try catch finally 面向CLR真实的结构,知道了双层过滤的机制,在异步编程模型中要注意下面这些情况。

二.注意多线程AsyncTask


       public static void TaskCatch()
        {
            try
            {
                var task = new Task(()=>throw new Exception());
                task.Start();
            }
            catch (Exception e)
            {
                //此时不能捕捉异常
            }
        }

上面的这段代码无法捕捉在task中产生的异常,因为线程栈或者说是上下文无法衔接了
task 中的异常无法传递给调用他的上一层try过滤。
解决方法很简单,在上一层try中同步下线程栈,可以使用task.wait()或者await task
关于同步 (异步Task) 其实也有很多的注意事项,尤其是在UI线程中使用要特别小心,可以参考这篇文章
C# 异步async 与 UI线程互锁问题分析处理

三.注意AsyncVoid(慎用)

   static async void ThrowExceptionAsync()
        {
            throw new Exception();
        }
   public static void TaskCatch()
        {
            try
            {
                ThrowExceptionAsync();
            }
            catch (Exception)
            {
                throw;//此时不能捕捉异常
            }
        }

这种情况,异常无法传递给调用他的上一层try过滤。为什么呢?因为此时堆栈帧已经发生了变化
这一点可以借助VS看到。
解决方法:
1.将可能发生异常的异步方法改成同步方法,或使用async task;
2.将try catch 放在异步方法中,并在此处理掉异常。

四.总结

多线程异步同步是个很大的话题,针对AsyncViod,在面向CLR端的IL代码也做了自动调整。
在异步方法或多线程异步时,我们需要小心使用try catch 的“冒泡“机制。尽量使用AsyncTask代替AsyncViod。且AsyncViod搭配await想实现同步功能时,并不算真正的同步,对于AsyncViod一定要慎用。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值