ASP.NET ConfigureAwait(false)写法是否防止同步方法调用async方法引发的应用程序崩溃

17 篇文章 1 订阅
4 篇文章 0 订阅

同步方法调用async方法引发的ASP.NET应用程序崩溃

https://blog.csdn.net/weixin_34208283/article/details/93603295

摘自上面的博客:

在ASP.NET中(ASP.NET天生是多线程的,基于线程池的,没有UI线程的概念),如果你调用了一个async方法,如果有await相伴,当前线程立马被释放回线程池,线程的上下文信息(比如reqeust context)被保存;如果没有await相伴(也没有其他的wait代码),调用async方法之后,代码会继续往下执行,直至完成,当前线程被释放回线程池,线程的上下文信息不会被保存。当async中的异步任务完成后(注:异步任务不是在另外一个线程中完成的,是在一个状态机中完成的),会从线程池中取出一个线程继续执行,执行时会读取当时调用它的原线程的上下文信息(默认情况下的行为,如果ConfigureAwait(false) ,就没有这一步操作),如果当初调用时没有使用await,线程的上下文信息没有被保存,这时就会引发NullReferenceException。而在这种级别发生的未处理null引用异常,会引发整个应用程序崩溃,更准确地说是应用程序所在的进程崩溃。

在ASP.NET中要么老老实实地await;要么告诉async方法,不要读取原线程的上下文信息(ConfigureAwait(false),未经实际验证是否有效);要么调用async方法的线程没有需要保存的上下文信息,比如在Task.Run(或Task.Factory.StartNew)中调用async方法,也就是用一个新的线程调用async方法。

我来测试下ConfigureAwait(false)是否可以防止呢?

ConfigureAwait(false)

        public string getPATData([FromUri]PATQuery patQuery)
        {
            try
            {
                Logs.Info($"主线程调用异步之前ID{Thread.CurrentThread.ManagedThreadId}执行");

                var data = new
                {
                    list = patService.GetPAT(patQuery).Result,
                    total = patQuery.records,
                };

                Logs.Info($"异步后的线程ID{Thread.CurrentThread.ManagedThreadId}同步上下文:{SynchronizationContext.Current?.ToString()}开始执行");

                return data.ToJson();
            }
            catch (Exception e)
            {
                Logs.LogWriter(e.GetOriginalException());
            }
            return string.Empty;
        }

PATService.cs

 public class PATService
    {
        public async Task<List<PATDto>> GetPAT(PATQuery patQuery)
        {
            try
            {

                using (MESDB db = new MESDB())
                {
                    var query = db.PATDto;

                    var result = await query.ToListAsync().ConfigureAwait(false);

                    return result;
                }
            }
            catch (Exception ex)
            {
            
            }
            return null;
        }
 }

输出日志如下:

2021-04-25 15:10:53.1943 INFO 主线程调用异步之前ID5执行
2021-04-25 15:10:53.7092 INFO 异步后的线程ID5同步上下文:System.Web.LegacyAspNetSynchronizationContext开始执行

结论:

上面的写法 await .ConfigureAwait(false) 防止崩溃。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值