在遇到“常见”异步死锁并从Async Best Practices获得进一步的理解之后,我尝试在ASP.NET中模拟该问题,以弄清楚为什么我们以前从未遇到过此问题。似乎不同之处在于,以前我们使用的是http客户端上的get async方法,但这并没有引起问题。

    public class DeadLockController : ApiController
    {
        /// <summary>
        /// Does not result in deadlock - but why?
        /// </summary>
        [HttpGet]
        public IHttpActionResult HttpDeadLock()
        {
            var client = new HttpClient();
            return Ok( client.GetStringAsync( "https://www.google.com/" ).Result );
        }

        /// <summary>
        /// Results in expected repeatable deadlock.
        /// </summary>
        [HttpGet]
        public IHttpActionResult DeadLock()
        {
            var delayTask = DelayAsync().Result;

            return Ok( delayTask );
        }

        /// <summary>
        /// Does not result in deadlock.
        /// </summary>
        [HttpGet]
        public async Task< IHttpActionResult > FixedDeadLock()
        {
            var delayTask = await DelayAsync();

            return Ok( delayTask );
        }

        private async Task< int > DelayAsync()
        {
           await Task.Delay( 1000 );
           return 0;
        }
    }


因此,如果要调用api/DeadLock/DeadLock,则会遇到本文所述的常见死锁。这是预期/理解的。 api/DeadLock/FixedDeadLock是解决此问题的“正确”方法。

但是,即使在概念上相同,调用api/DeadLock/HttpDeadLock也不会导致死锁,并且我不确定为什么吗?为什么HttpClient不会遇到此问题?理论上,Httpclient在内部进行等待。

最佳答案

api / DeadLock / HttpDeadLock不会死锁的原因是,在该代码中,您没有等待任何任务。

相反,您通过调用Task.Result同步等待任务来阻塞线程。

实现这种模式时,死锁通常是async-await和Task.Wait / Task.Result组合的组合。

07-24 20:05