COM服務器的僞異步技術及其實現

學識都 人氣:7.07K

摘要:COM組件技術在Windows操作系統中發揮了極其重要的作用,但標準COM組件技術在實時操作性上不盡完善。作爲補充可以用COM連接點技術和多線程技術來構造一種僞異步技術, 完成某些前者不能完成的任務。本文詳細描述了其實現原理,並根據技術細節提供了作者的解決方案。

COM服務器的僞異步技術及其實現

關鍵詞: COM;異步調用;連接點;接口;STA; MTA

1. COM異步技術
與普通同步執行的COM服務器不同,一個提供異步方法調用的COM服務器允許客戶程序以一種非阻塞的方式來訪問它,客戶程序可以在等待調用返回的過程中繼續進行別的工作,從而提高工作效率。 尤其隨着Windows2000和COM 的發佈,COM現在已經完全支持異步方法的調用了,通過IDL的定義,由MIDL編譯器爲接口的每個方法實現同步和異步兩種獨立的調用定義。但是COM提供的這種異步方法調用並非盡善盡美:
1) 這種技術發佈較晚,只在WIN2000下被支持,所以用它開發的軟件不能在Windows 95和Windows NT平臺上運行。
2) 客戶端使用不便,儘管COM通過MIDL生成的接口代理(proxy)與存根(stub)完成了大部分爲支持異步方法調用所做的工作,客戶端仍需要完成系列繁瑣的細節工作。
3) 無論客戶端還是服務器端都需要聚合由COM提供的對象,方法調用方式也有別於標準同步調用,因而不適用於標準ACTIVEX控件的'編寫,而ACTIVEX控件實質上是一種特殊的COM服務器。
由於上述一系列缺陷,往往需要一種替代解決辦法,通常可以用一些基本的COM技術來構造一種僞異步技術。

2. COM應用
這種僞異步技術是通過接口回調(interface callback)的方法來實現的,它基於兩項關鍵的COM技術: 連接點(Connection point)技術和COM多線程(Multithread)技術。
連接點技術的基礎是COM的出接口(outgoing interface)。出接口與普通的接口不一樣,它由COM服務器端進行定義,但卻由用戶程序來實現(此實現對象被稱爲接收器sink),並把接口指針告訴給COM服務器。由於出接口是在服務器的類型庫中定義, 所以COM服務器可以很方便的利用此接口指針與客戶進行通訊。但直接使用出接口,客戶程序和COM服務器都需要出接口有一定的瞭解,爲此COM又提供了連接點技術(可連接對象),如圖:

COM提供的可連接對象,通過IConnectionPointContainer接口管理所有的出接口。對應於每個出接口,可連接對象管理一個連接點對象,每一個連接點對象實現了IConnectionPoint接口,客戶通過連接點對象建立接收器與可連接對象的連接,且通過兩個枚舉器的引入,使得可連接對象支持多個出接口,而每個出接口支持多個與接收器的連接。明顯,連接點技術的實質是對出接口的一種封裝。通過使用連接點技術,COM服務器可以用一種非常常規的方法描述它的引出接口,併爲客戶程序提供了一種標準的方法來實現這些接口,對於實現服務器組件的標準化非常方便,也有利於客戶程序的獨立開發,符合中間件開發的原則。
COM多線程管理相當複雜,要實現多線程,應對COM的線程模型有深入的瞭解。COM支持兩種線程模型:單線程單元(STA,Single-Threaded Apartment)和多線程單元(MTA,MultiThreaded Apartment)。如圖所示:
單元是一種抽象的概念,定義了一組對象的邏輯集合,這些對象共享同一組併發性和重入限制,每個COM對象都只能屬於某一個單元。STA只能包含一個線程(單元線程),與32位Windows平臺上的用戶界面(UI)線程相似,單元線程擁有一個隱藏的窗口,所有對此線程中服務器組件方法的調用都被COM轉化爲消息(message),通過消息循環進行消息分發,並調用窗口過程保證調用到COM對象的成員函數中;而每個MTA可以包含多個線程(自由線程),自由線程相似於Windows平臺的工作(Work)線程,不帶消息分發,可以直接使用。每個進程只能有一個MTA,但是可以於有任意多個STA,每一個使用COM的線程必須通過調用CoInitialize(0)來新建一個STA,或者通過調用CoInitializeEx(0,COINT_MULTITHREAD)來創建或加入一個MTA,否則這個線程將出錯。服務器組件實體存在於線程中,要麼處於MTA中,要麼處在STA中,別無選擇。遵守如下規則:跨單元的接口指針傳遞需要調度,否則指針無效