3 回答

TA贡献1831条经验 获得超4个赞
您的程序从调用开始,Main完成后退出。
因为Main只是创建了一个实例,Program然后调用MakeBreakfast(),它Task会在遇到第一个时立即返回到 main await。因此Main几乎立即存在。
让我们稍微更改一下代码,看看是否是这种情况:
static void Main(string[] args)
{
Program p = new Program();
p.MakeBreakfast();
Console.WriteLine("Done!");
Console.ReadLine();
}
public async Task MakeBreakfast()
{
Console.WriteLine("Starting MakeBreakfast");
Thread.Sleep(1000);
Console.WriteLine("Calling await BoilWater()");
await BoilWater();
Console.WriteLine("Done await BoilWater()");
StartToaster();
PutTeainWater();
PutBreadinToaster();
SpreadButter();
}
现在,如果我让它运行完成,我会看到这个输出:
Starting MakeBreakfast
Calling await BoilWater()
BoilWater start
Done!
BoilWater end
Done await BoilWater()
StartToaster start
PutTeainWater start
StartToaster end
PutBreadinToaster start
SpreadButter start
SpreadButter end
PutTeainWater end
PutBreadinToaster end
代码确实点击了await然后返回到Main。
为了使代码正确完成,我们需要await一切。你有两种方法可以做到这一点:
(1)
static async Task Main(string[] args)
{
Program p = new Program();
await p.MakeBreakfast();
Console.WriteLine("Done!");
Console.ReadLine();
}
public async Task MakeBreakfast()
{
await BoilWater();
await StartToaster();
await PutTeainWater();
await PutBreadinToaster();
await SpreadButter();
}
现在当它运行时你会得到这个输出:
BoilWater start
BoilWater end
StartToaster start
StartToaster end
PutTeainWater start
PutTeainWater end
PutBreadinToaster start
PutBreadinToaster end
SpreadButter start
SpreadButter end
Done!
(2)
static async Task Main(string[] args)
{
Program p = new Program();
await p.MakeBreakfast();
Console.WriteLine("Done!");
Console.ReadLine();
}
public async Task MakeBreakfast()
{
var tasks = new[]
{
BoilWater(),
StartToaster(),
PutTeainWater(),
PutBreadinToaster(),
SpreadButter(),
};
await Task.WhenAll(tasks);
}
现在这个版本同时开始所有的早餐任务,但在返回之前等待它们全部完成。
你得到这个输出:
BoilWater start
StartToaster start
PutTeainWater start
PutBreadinToaster start
SpreadButter start
StartToaster end
SpreadButter end
BoilWater end
PutTeainWater end
PutBreadinToaster end
Done!
一种更符合逻辑的代码执行方式——先烧水,再泡茶;然后启动烤面包机,煮吐司,摊开吐司——可能是这样的:
public async Task MakeBreakfast()
{
async Task MakeTea()
{
await BoilWater();
await PutTeainWater();
}
async Task MakeToast()
{
await StartToaster();
await PutBreadinToaster();
await SpreadButter();
}
await Task.WhenAll(MakeTea(), MakeToast());
}
这给出了:
BoilWater start
StartToaster start
StartToaster end
PutBreadinToaster start
BoilWater end
PutTeainWater start
PutTeainWater end
PutBreadinToaster end
SpreadButter start
SpreadButter end
Done!

TA贡献1826条经验 获得超6个赞
异步方法的一般工作流程是同步运行 await 之前的代码(即按原样运行),然后返回一个任务对象,其中包含要等待的任务,而 await 之后的所有内容都作为该任务的延续任务完成时执行。
现在,如果只BoilWater
等待启动消息同步执行,所有其他调用将作为延续。由于MakeBreakfast
没有等待,程序将在BoilWater
完成/等待它们的毫秒之前执行,因此不会执行延续(即其他任务)。
如果BoilWater
没有等待,则其他MakeBreakfast
任务不会作为BoilWater
任务的延续。这意味着BoilWater
再次运行直到 Task.Delay 并将其作为任务返回。但是,由于没有等待此任务,因此下一个任务MakeBreakfast
将以相同的方式启动。所以本质上,所有MakeBreakfast
任务都是按顺序启动的,并且MakeBreakfast
只能在SpreadWater
启动时返回并返回它的任务。同样,任务仍在后台运行,等待它们的毫秒数,但程序在此时间范围之前退出,因此关闭消息延续没有机会运行。
- 3 回答
- 0 关注
- 205 浏览
添加回答
举报