c# - 异步编程试图了解 await 是如何工作的
问题描述
所以我正在学习一些基本的异步编程并遵循本教程: https ://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/但是我得到的输出与我不同我期待。
这是我的代码:
private async void btn1_Click(object sender, EventArgs e)
{
await TestAsync();
Console.WriteLine("terminate");
}
private async Task TestAsync()
{
string str = await Todo();
await Task.Delay(500); //added await operator as per FCin advice
Console.WriteLine(str);
}
private async Task<string> Todo()
{
await Task.Delay(3000); //added await operator as per FCin advice
return "return from async task";
}
从单击 btn1 开始,将触发 btn1_Click 方法。首先它将调用TestAsync()。由于TestAsync方法的第一行是等待一个async方法,所以我的理解是此时await操作符应该暂停TestAsync并将控制权返回给TestAsync的调用者,即btn1_Click。这应该打印“终止”,然后程序应该耐心等待 TestAsync 完成并最终打印“从异步任务返回”。但是我得到的输出是相反的顺序,我试图理解为什么。
所以我对其进行了修改,以便现在在 btn1_Click 方法中等待 TestAsync。我也将线程睡眠更改为任务延迟,但我仍然得到相同的输出......
Edit2:我用作示例的代码
// 1. Three things to note in the signature:
// - The method has an async modifier.
// - The return type is Task or Task<T>. (See "Return Types" section.)
// Here, it is Task<int> because the return statement returns an integer.
// - The method name ends in "Async."
async Task<int> AccessTheWebAsync()
{
// 2. You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// 3. GetStringAsync returns a Task<string>. That means that when you await
// the task you'll get a string (urlContents).
Task<string> getStringTask =
client.GetStringAsync("http://msdn.microsoft.com");
// 4 .You can do work here that doesn't rely on the string from
//GetStringAsync.
DoIndependentWork();
// 5. The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// 6. The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
解决方案
await 做它所说的,它等待。当您点击await
它时,它不会转到调用者方法,它会一直等到Todo
完成。现在,async/await
如果它等待,为什么要使用?因为在这个等待期间,它会做其他工作。它使您的 UI 保持运行。它处理来自消息队列的消息,例如单击按钮、绘制控件、计算光标是否击中任何会突出显示控件的边界框等。
您现在的代码是完全同步的,因为您不是在 await Task.Delay
。对于每个未等待的方法,您甚至可能会收到警告。
以下是这段代码的执行方式:
- 等待 3000 毫秒
- 返回“从异步任务返回”
- 等待 500 毫秒
- 打印“从异步任务返回”
- 打印“终止”
代码:
private async void btn1_Click(object sender, EventArgs e)
{
await TestAsync();
Console.WriteLine("terminate");
}
private async Task TestAsync()
{
string str = await Todo();
await Task.Delay(500);
Console.WriteLine(str);
}
private async Task<string> Todo()
{
await Task.Delay(3000);
return "return from async task";
}
推荐阅读
- javascript - 当它换行到新行时,我可以将 CSS 应用于 flex-item 吗?
- html - 为什么背景变黑但文本仍然是紫色(HTML CSS)?
- elasticsearch - curator-cli 和 curator 动作文件之间的区别
- python - DDS Openslice:如何在 python 中创建监听器
- javascript - 如何将多个单选按钮值作为参数传递?
- java - 使用Java比较2个字符数组中的字符
- javascript - 为什么我的 react 应用在 html 的正文中没有出现脚本标签?
- java - 如何防止用户访问android中应用程序的专用目录
- javascript - 连续禁用数组中的所有复选框
- r - 从 1970 年开始,R 中的情节改变 x 轴