Winform/WPF async/await容易引起死锁的解决办法
Posted lishuangquan1987
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Winform/WPF async/await容易引起死锁的解决办法相关的知识,希望对你有一定的参考价值。
在使用Winform或者WPF编程时,无论是使用.net framework 4.x还是使用.netcore 还是使用.net5,.net6,多多少少会使用到异步方法。如果是彻彻底底的使用异步,则不会发生死锁,但是有时候我们的系统框架都是用同步写的,突然第三方库只支持异步方法,这时候调用就要小心了,可能会引起界面卡死。
如下是模拟的情况:
新建一个winform项目。界面上有个按钮。点击这个按钮,调用异步方法。
代码如下:
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void button1_Click(object sender, EventArgs e)
var str = TestString().Result;
MessageBox.Show(str);
public async Task<string> TestString()
await Task.Delay(2000);
return "hello";
你会发现,这个时候,界面卡主了,会永远一直卡下去。
具体的原因分析:https://wenku.baidu.com/view/4f6ab3d49d3143323968011ca300a6c30c22f16f.html
https://blog.csdn.net/WPwalter/article/details/78370706
假定TestString
这个方法是别人第三方库提供的,那我们要如何调用
解决办法一(不推荐)
异步到底。全部使用异步。如果是小的项目,改一下无所谓。大的项目,不推荐:
public partial class Form1 : Form
public Form1()
InitializeComponent();
private async void button1_Click(object sender, EventArgs e)
var str =await TestString();
MessageBox.Show(str);
public async Task<string> TestString()
await Task.Delay(2000);
return "hello";
解决方案二(推荐)
使用Task.Run
包一层
public partial class Form1 : Form
public Form1()
InitializeComponent();
private void button1_Click(object sender, EventArgs e)
var (ok,str) =InvokeAsyncMethod(TestString,5000);
if (ok)
MessageBox.Show(str);
else
MessageBox.Show("调用超时");
public async Task<string> TestString()
await Task.Delay(2000);
return "hello";
public (bool,T) InvokeAsyncMethod<T>(Func<Task<T>> func, int timeout)
var result = Task.Run(async () => await func());
if (result.Wait(timeout))
return (true, result.Result);
else
return (false, default(T));
以上是关于Winform/WPF async/await容易引起死锁的解决办法的主要内容,如果未能解决你的问题,请参考以下文章
[ECMAScript] 说说你对async/await的理解?