本文链接: https://blog.csdn.net/lishuangquan1987/article/details/125082082
在使用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));
}
}
}
评论区