COM套間對.NET程序使用COM對象的影響(中)

COM裏面,套間是一個 想象中的邊界,用來在多線程環境中安全使用線程安全和線程不安全的COM對象。什麼叫做線程安全的COM對象呢?再多線程環境中,如果這個COM對象自己實現了同步機制,可以被多個線程同時調用而不破壞對象內部數據的完整性的話,那麼這個對象就叫做線程安全的對象。然而COM對象有一個目標就是,即使在多線程環境裏面也可以安全地使用線程不安全的COM對象。也就是說,即使COM對象內部沒有實現同步機制,COM也有一個機制可以創建一個線程安全的環境來使用這個對象,這個機制就是套間。在多線程環境裏面,套間爲線程不安全的COM對象創建了一個同步機制,COM保證在任意時刻都只有一個客戶端在調用線程不安全的COM對象(調用它的函數—COM世界裏面只有函數和接口)。

關於套間的知識,可以參考下面兩篇文章:

http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5529

http://www.codeguru.com/cpp/com-tech/activex/apts/article.php/c5533

而如果需要跨套間調用COM對象,這個函數調用,調用使用的參數和函數調用返回值都需要在套間之間被列集。而如果你的參數裏面使用到了COM接口的話,例如跨套間使用一個COM對象,並且調用這個對象的QueryInterface方法,QueryInterface返回的接口就需要被列集。COM庫使用CoMarshalInterThreadInterfaceInStream CoGetInterfaceAndReleaseStream來列集接口。

CoMarshalInterThreadInterfaceInStream 查詢註冊表HKEY_CLASSES_ROOT/Interface/{IID}/ProxyStubClsid32中要列集的接口是否註冊有列集程序(ProxyStub程序)。

1.       如果這個鍵值存在,CoMarshalInterThreadInterfaceInStream會激活裏面CLSID對應的COM對象來完成接口的列集;

2.       如果沒有這個鍵值,那麼說明沒有提供方法列集接口,因此QueryInterface返回E_NOINTERFACE

如果你細心一點的話,會發現很多接口的ProxyStubClsid32裏面的CLSID是一樣的,而且這些接口通常都會有另外一個子鍵:TypeLib。這是因爲手工編寫處理接口列集的COM對象的工作繁瑣又容易出錯,

1.       所以對於一些Dual接口,COM庫(實際上是OLEAUT32.dll)提供了一個通用的類來列集所有的Dual接口,它所需要的就是類型庫文件因爲類型庫裏面包含了所有COM對象的元數據(Meta Data);

2.       另外,對於非Dual接口,你也可以使用MIDL根據IDL文件生成對應的列集接口的COM對象。

這是在上一篇文章裏面例子程序裏面出現InvalidCastException的原因,後一篇我會介紹如何更改.NET代碼修復這個問題。

發佈了73 篇原創文章 · 獲贊 2 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章