在遇到“常见”异步死锁并从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组合的组合。