async方法阻塞了它正在执行的UI线程
本文关键字:执行 UI 线程 方法 async | 更新日期: 2023-09-27 18:17:48
在Winform中考虑以下代码。当我点击按钮时,我期望异步方法不应该阻塞它正在执行的UI线程。
然而,我发现按钮在异步方法调用期间被冻结…如果为真,async方法的意义是什么?我很困惑。
namespace WindowsFrmAsyn
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
async private void button1_Click(object sender, EventArgs e)
{
int contentlength = await AccessTheWebAsync();
tbResult.Text =
string.Format("Length of the downloaded string: {0}.", contentlength);
Debug.WriteLine(tbResult.Text);
}
async Task<int> AccessTheWebAsync()
{
Debug.WriteLine("Call AccessTheWebAsync");
Thread.Sleep(5000);
Debug.WriteLine("Call AccessTheWebAsync done");
tbResult.Text = "I am in AccessTheWebAsync";
return 1000;
}
}
}
编译器警告告诉你发生了什么:因为你的async
方法从来没有await
,它将同步运行。
Thread.Sleep
为同步操作;如果您想执行异步操作,请使用Task.Delay
:
async Task<int> AccessTheWebAsync()
{
Debug.WriteLine("Call AccessTheWebAsync");
await Task.Delay(5000);
Debug.WriteLine("Call AccessTheWebAsync done");
tbResult.Text = "I am in AccessTheWebAsync";
return 1000;
}
目前你在accessthewebsync中缺少await,因为你没有等待任何东西,所以所有代码都在主线程上运行。Async/await不会让方法在不同的线程上运行,除了你等待的部分。
方法必须是这样的。
async Task<int> AccessTheWebAsync()
{
// Console writeline
await Task.Delay(seconds);
// Console WriteLine.
return value;
}
因此,async方法中的await之前和之后的所有内容都在调用该方法的同一个线程上运行。你可以选择使用ConfigureAwait
,这是在库中常用的,这样等待之后的所有事情都将发生在等待完成的同一个线程上。
查看http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/async-await-faq.aspx获取更多关于async/await的信息
当您编写这样的代码时:
private async Task<int> DoStuffAsync()
{
return 0;
}
这样做是同步的,因为你没有使用await表达式。
注意警告:
This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
根据警告建议,您可以这样修改:
private async Task<int> DoStuffAsync()
{
return await Task.Run<int>(() =>
{
return 0;
});
}