多線程公寓
在多線程 Apartment 模型中,已初始化為自由線程的進程中的所有線程都位於單一 Apartment 中。 因此,不需要在線程之間封送處理。 線程不需要擷取和分派訊息,因為 COM 不會在此模型中使用視窗訊息。
對多線程 Apartment 中物件方法的呼叫可以在 Apartment 中的任何線程上執行。 沒有呼叫的串行化;許多呼叫可能會同時發生於相同方法或相同的物件。 在多線程 Apartment 中建立的對象必須能夠隨時處理來自其他線程之方法的呼叫。
因為對物件的呼叫不會以任何方式串行化,多線程物件並行會提供最高的效能,並充分利用多處理器硬體來進行跨線程、跨進程和跨機器呼叫。 不過,這表示對象的程式代碼必須在其介面實作中提供同步處理,通常是透過使用事件物件、重要區段、Mutex 或信號等同步處理基本類型,本節稍後會說明。 此外,因為物件不會控制正在存取它的線程存留期,所以不會將線程特定狀態儲存在物件中(在線程本機記憶體中)。
以下是多線程 Apartment 同步處理的一些重要考慮:
- COM 僅提供單個線程 Apartment 的呼叫同步處理。
- 多線程 Apartment 在撥打電話時不會接聽電話(在同一個線程上)。
- 多線程 Apartment 無法進行輸入同步處理呼叫。
- 異步呼叫會轉換成多線程 Apartment 中的同步呼叫。
- 訊息篩選不會針對多線程 Apartment 中的任何線程呼叫。
若要將線程初始化為自由線程,請呼叫 CoInitializeEx,並指定COINIT_MULTITHREADED。 如需進程內伺服器線程的資訊,請參閱 進程伺服器線程問題。
多個用戶端可以同時從不同的線程呼叫支援自由線程的物件。 在無線程的跨進程伺服器中,COM 透過 RPC 子系統,在伺服器進程中建立線程集區,而且用戶端呼叫(或多個用戶端呼叫)可以隨時由這些線程傳遞。 跨進程伺服器也必須在其類別處理站中實作同步處理。 自由線程、進程內物件可以接收來自用戶端多個線程的直接呼叫。
用戶端可以在多個線程中執行 COM 工作。 所有線程都屬於相同的多線程Apartment。 介面指標會從線程直接傳遞至多線程 Apartment 內的線程,因此介面指標不會在其線程之間封送處理。 訊息篩選器(IMessageFilter 的實作)不會用於多線程 Apartment。 用戶端線程會在對 Apartment 外物件的 COM 呼叫時暫停,並在呼叫傳回時繼續。 進程之間的呼叫仍由 RPC 處理。
使用自由線程模型初始化的線程必須實作自己的同步處理。 如本節稍早所述,Windows 會透過下列同步處理基本類型啟用此實作:
- 事件物件提供一種向一或多個線程發出事件發生訊號的方式。 進程內的任何線程都可以建立事件物件。 事件建立 函式 CreateEvent 會傳回事件的句柄。 建立事件對象之後,具有物件句柄的線程就可以在繼續執行之前等候它。
- 重要區段用於程式代碼區段,該程式代碼區段需要對某些共享數據進行獨佔存取,才能執行,而且該區段只供單一進程內的線程使用。 關鍵區段就像是一個轉捩點,一次只能通過一個線程,如下所示:
- 為了確保一次沒有一個以上的線程存取共用數據,進程的主要線程會配置全域CRITICAL_SECTION數據結構,並初始化其成員。 進入重要區段的線程會呼叫 EnterCriticalSection 函式,並修改數據結構的成員。
- 嘗試進入重要區段的線程會呼叫 EnterCriticalSection ,以檢查CRITICAL_SECTION數據結構是否已修改。 如果是,另一個線程目前位於關鍵區段,而後續線程會進入睡眠狀態。 離開重要區段的線程會呼叫 LeaveCriticalSection,以重設數據結構。 當線程離開重要區段時,系統會喚醒其中一個睡眠中的線程,然後進入關鍵區段。
- Mutexes 會執行與重要區段相同的函式,不同進程中執行的線程都可以存取 Mutex。 擁有 Mutex 物件就像在辯論中擁有地板一樣。 進程會藉由呼叫會傳回句柄的 CreateMutex 函式來建立 Mutex 物件。 要求 Mutex 物件的第一個線程會取得它的擁有權。 當線程完成 Mutex 時,擁有權會以先到先得、先服務的方式傳遞至其他線程。
- 旗號可用來維護某些可用資源的參考計數。 線程會呼叫 CreateSemaphore 函式,並將指標傳遞給資源、初始資源計數和最大資源計數,以建立資源的旗號。 此函式會傳回句柄。 要求資源的線程會在呼叫 WaitForSingleObject 函式時傳遞其號誌句柄。 旗號物件會輪詢資源,以判斷其是否可用。 如果是,旗號會遞減資源計數,並喚醒等候的線程。 如果計數為零,線程會保持睡眠狀態,直到另一個線程釋放資源,導致信號將計數遞增為一個。
相關主題