☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
concept-backend 進階

async/await 的真相:不是多執行緒

最大的誤解

❌ "async/await 會開新執行緒處理"
✅ "async/await 讓執行緒在等待時去做別的事"

比喻

你在餐廳點餐:

  • 同步:你站在櫃檯等,餐好了才離開(執行緒卡住等 I/O)
  • 非同步:你點完拿號碼牌回座位,叫號再去拿(執行緒被釋放,I/O 完成後回來)
// 同步:執行緒等 1 秒,這段時間什麼都不能做
var data = httpClient.GetStringAsync(url).Result; // ← 阻塞!

// 非同步:執行緒被釋放去處理其他 Request
var data = await httpClient.GetStringAsync(url); // ← 不阻塞

I/O-bound vs CPU-bound

類型 例子 該用什麼
I/O-bound 資料庫查詢、HTTP 請求、檔案讀寫 await(釋放執行緒等 I/O)
CPU-bound 影像處理、加密計算、大量迴圈 Task.Run()(真的開新執行緒)
// I/O-bound → await
var users = await _db.Users.ToListAsync(); // 執行緒被釋放等 DB 回應

// CPU-bound → Task.Run
var hash = await Task.Run(() => ComputeExpensiveHash(data)); // 丟到背景執行緒

為什麼 Web 需要 async?

同步的 Web Server(假設 100 個執行緒):
→ 100 個 Request 同時進來
→ 每個都在等 DB(500ms)
→ 第 101 個 Request:「沒有空的執行緒了!」→ 503 Service Unavailable

非同步的 Web Server:
→ 100 個 Request 同時進來
→ await DB 時,執行緒被釋放
→ 釋放的執行緒去處理第 101、102... 個 Request
→ DB 回應後,繼續處理原本的 Request
→ 同樣 100 個執行緒,能處理數千個並行 Request

常見陷阱

1. async void(別用)

// ❌ async void:例外無法被 catch
async void BadMethod() { throw new Exception(); } // 直接崩潰

// ✅ async Task:例外會被 Task 包住
async Task GoodMethod() { throw new Exception(); } // 可以被 await catch

2. .Result / .Wait()(別用)

// ❌ 同步等待非同步 → 可能死鎖
var data = GetDataAsync().Result; // ASP.NET 中會死鎖!

// ✅ 一路 await 到底
var data = await GetDataAsync();

3. 不需要 async 的 async

// ❌ 多餘的 async(只是轉傳)
async Task<User> GetUser(int id) {
    return await _repo.GetAsync(id); // 多一層狀態機,沒意義
}

// ✅ 直接回傳 Task
Task<User> GetUser(int id) {
    return _repo.GetAsync(id); // 少一層包裝,效能更好
}

執行緒 vs Task

Thread:作業系統層級,建立成本高(~1MB stack)
Task:CLR 層級,使用 ThreadPool,輕量
async/await:語法糖,編譯器轉成狀態機(State Machine)

await 不等於開新 Thread。await 只是告訴編譯器:「這裡可以暫停,等結果回來再繼續。」

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊