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 關注
- 241 瀏覽
添加回答
舉報