1. 程式人生 > >多線程調用COM組件的體會(CoInitialize)(轉)

多線程調用COM組件的體會(CoInitialize)(轉)

主線程 target line 所有 family normal ali 轉換 microsoft

原文轉自 https://www.cnblogs.com/manors/archive/2010/05/17/COM_Initialize_STA_MTA.html

與設備打交道時,我們經常用到COM組件,比如音視頻設備(麥克風、播放器、攝像頭等)。

調用任何COM組件之前,你必須首先初始化COM套件環境,即調用CoInitialize或CoInitializeEx。COM套件環境在線程的生存周期內有效,線程退出前需要調用CoUninitialize釋放COM套件。

所謂COM套件,實際上是微軟為了方便大家理解而起的一個名字,不過個人認為改名詞很難理解。COM套件只指COM組件運行時的環境,其中包括COM組件的數據、變量、線程調度方式。

COM套件分為兩種模式,單線程套件(STA)和多線程套件(MTA)。不要單從字面上理解,例如:STA並非只能用於單線程的程序,多線程程序依然可以使用。下面列出兩種套件模式的區別。

套件類型 說明 性能 兼容性 常見錯誤
STA 單線程套間,一個進程內所有COM組件都運行在主STA中,主STA就是第一個調用CoInitialize函數的線程。也就是說,即使你擁有多線程程序,但在不通線程同時操作COM組件的時候,COM組件會通過Windows消息、Event同步對象之類的機制把調用轉換到主STA執行,而主STA通常對應應用程序的主線程。這樣對STA套件內的任何COM組件操作,實際上是單線程操作,COM組件不必關心線程同步的細節,因為根本沒有必要進行線程同步。
如果一個COM組件是MTA的,可以安全的運行與STA套件中。 由於STA套件所有的COM組件代碼都運行於主STA(第一個調用CoInitialize函數的線程),如果你的主線程沒有調用CoInitialize,那麽第一個調用CoInitialize的工作線程就會成為主STA,而工作線程隨時可能中止,這種情況下,一旦工作線程中止主STA也就不復存在了,因此你需要在主線程中調用CoInitialize初始化主STA,即使主線程不使用任何COM組件。
MTA 多線程套間,所有COM組件都運行在本線程的MTA套件中。這是就會出現多個線程同時執行某個COM調用,COM組件的開發者必須預料並處理這種並發訪問帶來的內存競爭讀寫混亂。COM組件開發者通常會應用臨界區、互斥量、信號燈之類的常規線程同步方法。而調用者,不需要擔心COM組件是否會因為多線程掛掉。
如果一個COM組件是STA的,被錯誤的運行與MTA套件會引發各種奇怪的錯誤。 把STA的COM組件運行於MTA套件中會引發錯誤。

這就會引出一個問題,到底我該使用STA還是MTA呢,答案很簡單問該COM組件的開發者,或者看他的說明文檔,他們會告訴你。

多線程調用COM組件的體會(CoInitialize)(轉)