在ASP.NET Core中,當一個HTTP請求到達伺服器時,它會被分配給執行緒池中的一個執行緒來處理。該執行緒會執行相應的Controller方法。
如果這個方法是一個非同步方法並且使用了await關鍵字,那麼在await的程式碼執行完畢之前,這個執行緒會被釋放回執行緒池,可以用來處理其他的HTTP請求。
當await的程式碼執行完畢後,ASP.NET Core會從執行緒池中再次獲取一個執行緒來繼續執行剩餘的程式碼。
在await運運算元之後的程式碼塊是作為一個回撥函式註冊到了任務中。當await的任務完成時,這個回撥函式會被執行。這個回撥函式可能會在原來的執行緒上執行,也可能在一個新的執行緒上執行,
這主要取決於所使用的SynchronizationContext(同步上下文)。
在ASP.NET Core中,預設情況下,每個請求都有自己的SynchronizationContext。當await操作在這種情況下被呼叫時,它會捕獲當前的SynchronizationContext,並在任務完成後在這個SynchronizationContext上執行回撥。
由於每個請求都有自己的SynchronizationContext,所以即使回撥在一個新的執行緒上執行,它仍然可以訪問到請求開始時的所有上下文資訊,如HttpContext。
SynchronizationContext和執行緒上下文是兩個不同的概念,它們在.NET中扮演著不同的角色。
執行緒上下文通常指的是與特定執行緒相關的一組資料或狀態資訊。這包括執行緒的區域性儲存(Thread Local Storage, TLS)以及其他一些執行緒特有的狀態。例如,在.NET中,每個執行緒都有自己的執行上下文(ExecutionContext),它包含了執行緒的安全上下文、邏輯呼叫上下文和執行緒本地儲存等資訊。
SynchronizationContext則是.NET中的一個抽象類,它定義了一種機制,用於在多執行緒環境中控制和協調程式碼的執行。SynchronizationContext的主要職責是決定在何處(即在哪個執行緒上)執行特定的程式碼塊。例如,Windows Forms和WPF框架都提供了自己的SynchronizationContext實現,用於確保只有UI執行緒可以訪問UI元素。
當在.NET中使用async/await模式時,await運運算元會捕獲當前的SynchronizationContext,並在非同步操作完成後在該SynchronizationContext上執行剩餘的程式碼。這是.NET非同步程式設計模型的一個關鍵部分,它使得非同步程式碼可以正確地在原始上下文(可能是UI執行緒,也可能是ASP.NET請求執行緒)上繼續執行,儘管在等待非同步操作完成的過程中,原始執行緒可能已經被釋放並用於執行其他任務。