浅谈浅谈C# async await 死锁问题总结死锁问题总结
可能发生死锁的程序类型可能发生死锁的程序类型
1、WPF/WinForm程序
2、asp.net (不包括asp.net core)程序
死锁的产生原理死锁的产生原理
对异步方法返回的Task调用Wait()或访问Result属性时,可能会产生死锁。
下面的WPF代码会出现死锁:
private void Button_Click_7(object sender, RoutedEventArgs e)
{
Method1().Wait();
}
private async Task Method1()
{
await Task.Delay(100);
txtLog.AppendText("后续代码");
}
下面的asp.net mvc代码也会出现死锁:
public ActionResult Index()
{
string s=Method1().Result;
return View();
}
private async Task<string> Method1()
{
await Task.Delay(100);
return "hello";
}
以WPF代码为例,事件处理器调用Method1,得到Task对象,然后调用Task的Wait方法,阻塞自己所在的线程,即主线程,
直到Task对象“完成”。而返回的Task对象要想“完成”,必须在主线程上执行await之后的代码。而主线程早就处于阻塞状态,它
在等待Task对象完成!于是死锁就产生了。
asp.net mvc代码是同样的道理。
什么时候必然会死锁,如何避免什么时候必然会死锁,如何避免
从上面的两个例子中似乎可以得出结论:在WPF/WinForm/asp.net程序中,在异步方法上调用.Result/Wait(),就会产生死
锁。然而事实并非如此。
如下面的WPF代码就不会出现死锁:(从web获取数据并显示在文本框中。此代码仅为举例说明,异步事件处理器才是正
道)
private void Button_Click_8(object sender, RoutedEventArgs e)
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://www.baidu.com/");
string html = httpClient.GetStringAsync("/").Result; html = "【" + html + "】";
txtLog.AppendText(html);
}
把获取数据的代码摘出来吧:
private void Button_Click_8(object sender, RoutedEventArgs e)
{