试图用ASP.NET和HttpClient()理解“常见”的异步死锁

时间:2015-12-16 16:46:09

标签: c# asp.net asynchronous async-await

在遇到“常见”异步死锁并从Async Best Practices获得进一步理解之后,我尝试在ASP.NET中模拟该问题,试图弄清楚为什么我们之前从未遇到过这个问题。看来差异在于以前我们使用http客户端获取异步方法并且没有引起问题。

    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正在内部进行等待。

1 个答案:

答案 0 :(得分:3)

api / DeadLock / HttpDeadLock没有死锁的原因是因为在该代码中你没有等待任何任务。

您可以通过调用Task.Result同步等待任务来阻止线程。

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