问题

首先,在ASP.NET MVC 环境下对async返回的Task执行Wait()会导致线程死锁。例:

        public ActionResult Asv2()
        {
            //dead lock
            var task = AssignValue2();
            task.Wait();
            return Content(_container);
        }
 
        private void Assign()
        {
            _container = "Hello World";
        }

        public async Task AssignValue2()
        {
            await Task.Delay(500);
            await Task.Run(() => Assign());
        }   

这是由于async方法注册的回调要求返回到调用async的线程——而在主线程(action方法所在线程)中又对Task执行了Wait(),相互等待,导致了死锁。

Wait一个async方法是否一定导致死锁(ASP.NET MVC)

否。Task类型的对象有一个ConfigureAwait方法,将参数置为false可以防止回调返回当前线程。但是有一个前提条件:async方法的调用链中的所有async方法都必须指定ConfigureAwait(false)。例:

        public async Task AssignValue2()
        {
            await Task.Delay(500);
            await Task.Run(() => Assign());
        }

        public async Task AssignValue()
        {
            await Task.Run(() => Assign()).ConfigureAwait(false);
        }

        public async Task Wrapped()
        {
            await AssignValue().ConfigureAwait(false);
        }

        public async Task Wrapped2()
        {
            await AssignValue2().ConfigureAwait(false);
        }

        public async Task Update()
        {
            await Task.Run(() => { _container = _container + "Hello "; });
        }

        public async Task Update2()
        {
            await Task.Run(() => { _container = _container + "World"; });
        }

        #region 基本调用

        /// <summary>
        /// 调用层次最深的异步方法(第一个调用的异步方法)不要求返回到主线程
        /// </summary>
        /// <returns></returns>
        public ActionResult Asv1()
        {
            var task = AssignValue();
            task.Wait();
            return Content(_container);
        }

        /// <summary>
        /// ...返回主线程
        /// </summary>
        /// <returns></returns>
        public ActionResult Asv2()
        {
            //dead lock
            var task = AssignValue2();
            task.Wait();
            return Content(_container);
        }

        /// <summary>
        /// 所有都不要求返回主线程
        /// </summary>
        /// <returns></returns>
        public ActionResult Wrp()
        {
            var task = Wrapped();
            task.Wait();
            return Content(_container);
        }

        /// <summary>
        /// 其中一个要求返回主线程
        /// </summary>
        /// <returns></returns>
        public ActionResult Wrp2()
        {
            //dead lock
            var task = Wrapped2();
            task.Wait();
            return Content(_container);
        }

        #endregion
对比

相关文章:

  • 2021-11-11
  • 2021-09-14
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-12-30
  • 2022-01-22
  • 2022-12-23
  • 2021-06-15
  • 2022-12-23
相关资源
相似解决方案