在遇到“常见”异步死锁并从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正在内部进行等待。
答案 0 :(得分:3)
api / DeadLock / HttpDeadLock没有死锁的原因是因为在该代码中你没有等待任何任务。
您可以通过调用Task.Result同步等待任务来阻止线程。
实现这种模式时的死锁通常会出现async-await和Task.Wait / Task.Result组合的组合。