Buy Me a Coffee

從頭實作 CSharp async/await 教學

想要精通 CSharp 中 async/await 的運作原理嗎?最近,微軟工程師 Stephen Toub 分享了一段精彩教學,從頭開始實作出一個簡易版的 async/await 機制。這不僅有助於深入理解這個強大的非同步程式設計工具,也能讓您更好地利用它的能力。

摘要自下列 Youtube 影片

緣起

async/await 雖然在 CSharp 5.0 就已推出,但它的運作原理仍有許多人感到陌生。為了幫助開發人員更透徹地理解這個功能,Toub 製作了這段教學影片,以解說的方式逐步實作出一個簡易版本的 async/await。

概述

這個教學首先從實作一個簡單的執行緒池(Thread Pool)開始。然後基於此執行緒池,實作出核心的 Task 類別,讓非同步操作可以被表示與追蹤。接著介紹用於處理非同步操作結果的各種機制,如 continuationsawait 等。最後實作出一個讓 await 可運作於自製 Task 類別的方法。

以下是教學中實作的主要元件:

元件說明
MyThreadPool一個簡單的執行緒池,用於執行非同步工作
MyTask代表非同步操作的類別,類似於 .NET 的 Task
MyTask.Run在執行緒池中執行指定的工作,並傳回一個 MyTask 物件
MyTask.WhenAll等待多個 MyTask 完成
MyTask.Delay延遲指定的時間後完成一個 MyTask
MyTask.Iterate實作 async 迴圈,讓非同步工作可以像同步迴圈般執行
MyTask.Awaiter讓自製的 MyTask 物件可使用 await 關鍵字

重點解析

  1. 執行緒池:為了模擬真實的非同步操作環境,Toub 首先實作了一個簡易的執行緒池。他解釋了在非同步程式設計中,asynchrony 與 concurrency 的差異,以及為何需要使用執行緒池。

  2. Task 類別:接著實作了代表非同步操作的 Task 類別。這個類別追蹤操作的狀態、結果以及例外狀況。同時也實作了用於等待操作完成的機制。

  3. 執行環境(Execution Context):在討論如何實作 await 時,Toub 強調了 “執行環境” 的重要性。每個非同步操作都需要保留當下的執行環境,以確保在操作完成後能正確地恢復狀態。他示範了如何使用 AsyncLocal 類別來達成此目的。

  4. ContinuationsContinuation 是一個在非同步操作完成後會被調用的委派。Toub 展示了如何使用它們來實作 awaitWhenAll 等功能。

  5. 語法糖(Syntactic Sugar):最後,Toub 解釋了 CSharp 編譯器如何將 async/await 語法轉換為較低層級的操作,展現了這個功能背後的真正實作。

總結

透過這段教學,Toub 清楚地解釋了 async/await 背後的運作原理,讓開發人員能夠更深入地理解這個強大的程式設計工具。即使您不打算自己實作這些功能,了解它們的運作方式也能幫助您更好地利用 async/await,並避免常見的誤用情況。

無論您是 CSharp 新手還是經驗老到,這份教學獻給所有想要提升技能的開發人員。開放思維、積極學習,才是成為優秀工程師的不二法門。

關於作者:Stephen Toub 是微軟的一位資深軟體工程師,專精於 .NET 平台核心技術,也是 CSharp 語言規格的設計團隊成員。他熱衷於透過教學與分享,協助開發人員充分利用 .NET 技術的能力。