c# 冗餘的 await 調用
最近在CodeReview一些程式碼的時候,看到這行字
冗餘的 await 調用
• 如果結果已經是 Task,不需要重複 await,這樣可以簡化代碼。
想起來有時候我們確實在一些方法並沒有回傳值的問題而定義了回傳的Task
但這時候使用端仍往往習慣去await這個Task
這時建議的移除await,”似乎”是反習慣性的建議
因此我想說,用一些具體的例子,看一下在async 方法下 不去await一個 Task方法時,會不會有什麼影響
結論: 不會有影響~
簡易的程式碼如下:
Program.cs
Console.WriteLine("1");
var test = new Test();
test.Method1();
Console.WriteLine("2");
Console.ReadLine();
public class Test
{
async Task Method2()
{
Console.WriteLine("3");
}
async Task<int> Method3()
{
Console.WriteLine("6");
return 7;
}
public void Method1()
{
Method2();
Console.WriteLine("4");
var value = Method3();
Console.WriteLine("5");
Console.WriteLine(value.Result);
}
}
Console的執行順序結果會打印 出什麼結果?
5 Replies to “c# 冗餘的 await 調用”
以下來自於ChatGPT
根據你的程式碼,以下是程式的執行流程以及 Console 打印的順序:
程式執行的步驟:
1. Console.WriteLine(“1”); —— 打印 1。
2. var test = new Test(); —— 創建 Test 類的實例。
3. test.Method1(); —— 呼叫 Method1() 方法。
• Method1() 方法中,首先呼叫了 Method2(),但由於 Method2() 是 async,它返回的是一個 Task,但沒有 await 去等待它,所以方法內的代碼會立即繼續執行,而不等待 Method2() 完成。於是打印 3,但這個任務會在後台進行,並立即返回控制權給 Method1()。
• 然後,Console.WriteLine(“4”); 被執行,打印 4。
• 接著,var value = Method3(); 呼叫了 Method3(),但同樣,由於沒有 await,Method3() 返回的是一個 Task,程式不會等待它完成。此時 Method3() 的內部代碼被執行,打印 6,但返回的 Task 並不會立即給出結果,因為異步操作仍在進行。
• Console.WriteLine(“5”); 緊接著執行,打印 5。
• 然後 Console.WriteLine(value.Result); 這行代碼會阻塞,直到 Method3() 的 Task 完成,並且獲得其結果。由於 Method3() 返回的是 7,因此打印 7。
4. Console.WriteLine(“2”); —— 當 Method1() 完成後,程式繼續執行這行代碼,打印 2。
5. Console.ReadLine(); —— 等待用戶輸入,以防程式結束。
最終輸出順序:
1
3
4
6
5
7
2
第一次跑 Claude3.5
public async Task Method1()
{
await Method2();
Console.WriteLine(“4”);
var value = await Method3();
Console.WriteLine(“5”);
Console.WriteLine(value);
}
讓我解釋這段程式碼的執行順序。這是一個關於非同步程式(async/await)的重要概念。
執行順序會是:
Copy1
3
4
5
6
7
讓我解釋為什麼:
首先 Console.WriteLine(“1”) 執行,打印 “1”
創建 Test 實例並呼叫 Method1()
在 Method1() 中:
呼叫 Method2(),因為沒有使用 await,Method2 會開始執行並立即返回
Method2() 會打印 “3”
接著打印 “4”
呼叫 Method3(),同樣沒有使用 await
打印 “5”
訪問 value.Result 會阻塞線程直到 Method3 完成
Method3 執行並打印 “6”
Method3 返回值 7 被打印出來
關鍵點:
因為沒有使用 await 關鍵字,async 方法的呼叫會立即返回
使用 .Result 會造成同步等待,這可能導致死鎖風險
這種寫法並不是最佳實踐,建議使用 await 來正確處理非同步操作
如果想要正確處理非同步操作,程式碼應該改寫成:
csharpCopypublic async Task Method1()
{
await Method2();
Console.WriteLine(“4”);
var value = await Method3();
Console.WriteLine(“5”);
Console.WriteLine(value);
}
2去哪了?
/Users/paul_huang/Dev/FirstConsoleApp/FirstConsoleApp/bin/Debug/net7.0/FirstConsoleApp
1
3
4
6
5
7
2
再跑一次Claude3.5
讓我幫你分析這段程式碼的執行順序。
這段程式碼涉及非同步執行,需要特別注意 async/await 的行為。讓我們一步步分析:
首先執行 Console.WriteLine(“1”)
創建 Test 實例並呼叫 Method1()
在 Method1() 中:
呼叫 Method2() 但沒有 await,所以不會等待它完成
立即執行 Console.WriteLine(“4”)
呼叫 Method3() 但同樣沒有 await
立即執行 Console.WriteLine(“5”)
使用 .Result 會強制等待 Method3() 完成
Method3() 執行時會打印 “6”,然後返回 7
最後打印 value.Result (即 7)
程式最後執行 Console.WriteLine(“2”)
因此,輸出順序會是:
Copy1
4
5
6
7
2
注意:
“3” 雖然在 Method2() 中,但因為沒有 await 且沒有強制等待其結果,所以可能不會被打印出來
如果想要確保 Method2() 執行,應該使用 await Method2()
當前的程式碼有潛在的問題,因為非同步方法沒有正確地使用 await,可能會導致未預期的行為