c# - “等待”什么时候会立即离开一个方法,什么时候不会?
问题描述
在使用 async-await 的程序中,我的理解是这样的:
- 未等待的异步方法将在后台运行(?),其余代码将在此非等待方法完成之前继续执行
- 等待的异步方法将等待该方法完成,然后再继续执行下一行代码
下面的应用程序是我编写的,以检查上述陈述是否正确。
using System;
using System.Threading.Tasks;
namespace ConsoleApp3
{
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("Hello World!");
DoJob();
var z = 3;
Console.ReadLine();
}
static async Task DoJob()
{
var work1 = new WorkClass();
var work2 = new WorkClass();
while (true)
{
await work1.DoWork(500);
await work2.DoWork(1500);
}
}
}
public class WorkClass
{
public async Task DoWork(int delayMs)
{
var x = 1;
await Task.Delay(delayMs);
var y = 2;
}
}
}
以下是我的一些观察:
DoJob();
不等待呼叫。但是,调试器向我显示 DoJob 内部的代码正在执行,就好像它是一个普通的非异步方法一样。- 当代码执行到 时
await work1.DoWork(500);
,我会想“好的,所以现在DoJob
方法可能会被留下并被var z = 3;
执行?毕竟,'await' 应该离开方法。” 实际上,它只是进入DoWork
而不离开DoJob
-var z = 3;
仍然没有执行。 - 最后,当执行到达时
await Task.Delay(delayMs);
,DoJob
离开,var z = 3;
到达。之后,Delay
执行之后的代码。
我不明白的事情:
- 为什么
await Task.Delay(delayMs);
离开DoJob
方法,但await work1.DoWork(500);
没有? - 我看到它
DoJob
正在正常执行。我认为它会在后台完成(可能是由线程池线程之一?)。如果它是某种长时间运行的方法,看起来它可能会阻塞线程,对吗?
解决方案
为什么等待 Task.Delay(delayMs); 离开 DoJob 方法,但等待 work1.DoWork(500); 才不是?
因为这段代码:
await work1.DoWork(500);
与此代码相同:
var task = work1.DoWork(500);
await task;
因此,您的代码首先调用该方法,然后等待返回的任务。通常将其await
称为“等待方法调用”,但这并不是实际发生的情况 - 从技术上讲,方法调用首先(同步)完成,然后等待返回的任务。
我看到 DoJob 正在正常执行。我认为它会在后台完成(可能是由线程池线程之一?)。
不; 对于真正的异步操作,没有线程在该操作上被阻塞。
如果它是某种长时间运行的方法,看起来它可能会阻塞线程,对吗?
是的。
我的理解是这样的
我建议阅读我的异步介绍以获得更好的心理框架。总之:
async
启用await
关键字。它还生成一个状态机来处理创建Task
返回值之类的东西。await
对“等待”(通常是任务)进行操作。首先,它检查它是否已经完成;如果是,则该async
方法继续同步执行。- 如果 awaitable 尚未完成,则
await
(默认情况下)捕获其上下文并async
在 awaitable 完成时安排继续在该上下文上运行的方法。
推荐阅读
- javascript - Javascript:在启动用户触发操作之前等待 AJAX 调用完成
- react-native - 如何在mac os终端上使用放大添加通知命令添加添加(p12)证书的路径?
- javascript - 多个内联插入到表中
- opencv - 长焦镜头对大图像的相机标定误差较大
- laravel-5 - 模型创建后数据未真实保存在数据库中
- python - 我的 app.py 无法在后端接收请求并收到 404 错误
- javascript - 使用 react-apollo 进行服务器端渲染
- gradle - Beam 管道在直接运行器上运行正常时未在 Google Dataflow 中移动
- mysql - SQL 年龄组和唯一编号
- reactjs - 添加钩子组件时,比上一次渲染时渲染的钩子更多