進程、線程和 Apartment

進程是虛擬記憶體空間、程式代碼、資料和系統資源的集合。 線程是在進程內串行化執行的程序代碼。 處理器會執行線程,而不是進程,因此每個應用程式至少有一個進程,而且進程一律至少有一個線程執行,稱為主要線程。 除了主要線程之外,進程還可以有多個線程。

進程會透過訊息彼此通訊,使用 Microsoft 的遠端過程調用 (RPC) 技術將資訊傳遞至彼此。 遠端電腦上來自進程的呼叫與來自相同電腦上另一個進程的呼叫之間沒有任何差異。

當線程開始執行時,它會繼續執行,直到它終止,或直到它被優先順序較高的線程中斷為止(由用戶動作或核心的線程排程器)。 每個線程都可以執行個別的程式代碼區段,或多個線程可以執行相同的程式代碼區段。 執行相同程式代碼區塊的線程會維護不同的堆疊。 進程中的每個線程都會共用該進程的全域變數和資源。

線程排程器會根據進程的優先順序類別屬性和線程基底優先順序的組合,決定線程執行線程的時機和頻率。 您可以藉由呼叫 SetPriorityClass 函式來設定進程的優先順序類別屬性,並使用 SetThreadPriority 的呼叫來設定線程的基底優先順序。

多線程應用程式必須避免兩個線程問題: 死結競爭。 當每個線程正在等候另一個線程執行某些動作時,就會發生死結。 COM 呼叫控件有助於防止對象之間呼叫中的死結。 當某個線程在另一個線程相依之前完成時,就會發生競爭狀況,導致前者使用未初始化的值,因為後者尚未提供有效的值。 COM 提供一些專為協助避免跨進程伺服器競爭狀況而設計的函式。 (請參閱 跨行程伺服器實作協助程式。)

Apartment 和 COM 線程架構

雖然 COM 支援在導入多個線程之前普遍存在的單個線程個別進程模型,但您可以撰寫程式代碼來利用多個線程,進而產生更有效率的應用程式,方法是允許執行一個線程,而另一個線程會等候一些耗時的作業完成。

注意

使用多個線程並不保證效能更好。 事實上,因為線程分解是一個困難的問題,使用多個線程通常會導致效能問題。 索引鍵是只有在您非常確定您正在做什麼時,才使用多個線程。

 

一般而言,檢視 COM 線程架構最簡單的方式是將程式中的所有 COM 對象視為分成稱為 Apartment 的群組。 COM 物件只存在於一個 Apartment 中,也就是說,其方法只能由屬於該 Apartment 的線程直接呼叫。 任何其他想要呼叫 對象的線程都必須通過 Proxy。

有兩種類型的公寓: 單個線程公寓多線程公寓

  • 單個線程 Apartment 只包含一個線程,因此生活在單個線程 Apartment 中的所有 COM 物件只能從屬於該 Apartment 的一個線程接收方法呼叫。 對單個線程 Apartment 中 COM 物件的所有方法呼叫都會與單個線程 Apartment 線程的 Windows 消息佇列同步處理。 執行單個線程的進程只是此模型的特殊案例。
  • 多線程 Apartment 是由一或多個線程所組成,因此生活在多線程 Apartment 中的所有 COM 物件都可以直接從屬於多線程 Apartment 的任何線程接收方法呼叫。 多線程 Apartment 中的線程會使用稱為 自由線程的模型。 多線程 Apartment 中 COM 物件的呼叫會由物件本身同步處理。

注意

如需同一進程內單個線程 Apartment 與多線程 Apartment 之間的通訊描述,請參閱 單個線程和多線程通訊

 

進程可以有零或多個單個線程 Apartment,以及零或一個多線程 Apartment。

在程式中,主要 Apartment 是第一個要初始化的公寓。 在單個線程進程中,這是唯一的 Apartment。 呼叫參數會在 Apartment 之間封送處理,而 COM 會透過傳訊處理同步處理。 如果您將進程中的多個線程指定為自由線程,則所有免費線程都位於單一 Apartment 中,參數會直接傳遞至 Apartment 中的任何線程,而且您必須處理所有同步處理。 在具有自由線程和 Apartment 線程的進程中,所有免費線程都位於單一 Apartment 中,而所有其他 Apartment 都是單個線程 Apartment。 執行 COM 工作的程式是 Apartment 集合,其中最多一個多線程 Apartment,但任意數目的單線程 Apartment。

COM 中的線程模型為使用不同線程架構的用戶端和伺服器提供機制,以共同運作。 自然支援在不同進程中具有不同線程模型的對象之間的呼叫。 從呼叫對象的觀點來看,無論呼叫的對像是線程的方式,所有對進程外部物件的呼叫行為都相同。 同樣地,從所呼叫對象的觀點來看,無論呼叫端的線程模型為何,抵達呼叫的行為都相同。

用戶端與跨進程對象之間的互動很簡單,即使它們使用不同的線程模型,因為客戶端和物件在不同的進程中。 用戶端與伺服器之間的 COM 可以使用標準封送處理和 RPC,提供線程模型互通的程式代碼。 例如,如果多個自由線程用戶端同時呼叫單個線程物件,COM 會藉由將對應的視窗訊息放在伺服器消息佇列中來同步處理呼叫。 每次擷取和分派訊息時,物件的Apartment都會收到一個呼叫。 不過,請務必小心確保同進程伺服器與其客戶端正確互動。 (請參閱 行程伺服器線程問題。)

使用多線程模型進行程序設計最重要的問題是讓您的程式代碼安全無虞,讓特定線程的訊息只會移至該線程,並保護線程的存取權。

如需詳細資訊,請參閱下列主題: