早期使用 Thread 直接管理線程,缺乏返回值支援、線程池整合與異常處理機制,資源開銷大,難以協調多線程協作。
Task 代表非同步操作的未來結果,內建線程池支援(Task.Run),提供返回值(Task<TResult>)、延續(ContinueWith)、等待(Wait/Result)等豐富 API,成為 .NET 4.0+ 並行計算的核心。
var dayName = Task.Run<string>(() => GetDayOfThisWeek());
Console.WriteLine($"今天是:{dayName.Result}");
.NET 4.5 引入 async/await,編譯器自動生成狀態機,將非同步代碼轉為同步風格,極大簡化錯誤處理、併發控制與代碼可讀性。
await 不會開啟新線程,僅註冊延續;真正的異步由 Task.Run 或 I/O 完成埠驅動。await task 等價於 task.GetAwaiter().GetResult(),若任務未完成則掛起當前線程(UI 線程除外),完成後恢復執行。| 模式 | 特點 | 適用場景 |
|---|---|---|
| Callback | 回調地獄,錯誤處理分散 | 簡單單次異步 |
| Listener/Observer | 事件驅動,支援多訂閱者 | UI 事件、訊息總線 |
| Promise/Future | 鏈式調用(then),統一錯誤處理 | 複雜依賴鏈、併發協調 |
| async/await | 同步寫法,編譯器生成狀態機 | 現代 .NET 應用首選 |
最早模式,BeginXxx/EndXxx 配對,需手動管理 IAsyncResult,代碼碎片化嚴重。
XxxAsync 方法 + XxxCompleted 事件,支援進度報告與取消,但取消機制不具備可組合性。
統一以 Task 為核心,支援取消(CancellationToken)、進度(IProgress<T>)、併發控制(Task.WhenAll/WhenAny),成為現代標準。
編譯後不創建新線程,僅將方法轉為狀態機。真正異步發生在 HttpClient.GetStringAsync 等內部使用 Task.Run 或 I/O 完成埠的 API 中。
// 等待任務完成並獲取結果
var result = task.GetAwaiter().GetResult(); // 可能阻塞
// 或
var result = await task; // 非阻塞註冊延續
GetAwaiter() 返回 IAwaiter,其 GetResult() 會在任務未完成時掛起線程。若任務已完成則直接返回結果,實現「熱任務」優化。
Java Future.get() 類似 await,阻塞等待結果;Executor 對應 TaskScheduler;ForkJoinPool 解決線程限制問題。