2011-10-28 102 views
4

第一次使用COM 我有這個COM DLL,說ABCServer.dll,我創建了一個RCW並在我的項目中添加引用它。現在我的應用程序創建了多個線程,每個線程都從COM DLL創建某些類並與它們一起工作。但是,然後每個線程正在等待,而其他線程正在從COM DLL的某些類工作。COM多線程支持

修改我的應用程序的整個目的是啓用多線程。現在當多線程發生在我身邊時,COM使它成爲順序的。雖然每個線程都在創建新實例,但他們爲什麼還在等待其他人被處理?

+0

是您的COM組件聲明單線程單元(STA)或者多線程公寓(MTA)? – Seb

+0

如何以及在哪裏檢查? – EagerToLearn

+0

@EagerToLearn看到http://stackoverflow.com/questions/2722867/how-to-determine-threading-model-of-given-com-library – shf301

回答

1

到目前爲止發佈的評論和答案中存在相當大的混淆。 STA或MTA是線程的屬性。但重要的是COM組件需要什麼。這是在ThreadingModel註冊表值中聲明的。你找到了「公寓」,這是一個非常普遍的設置。這意味着該組件不支持線程。

這與.NET框架中的絕大多數類沒有什麼不同,很少有線程安全的。最大的區別是COM 強制執行線程安全性。使用.NET類,您需要編寫代碼,以便以線程安全的方式使用類對象。這是很難得到正確的,並且很難診斷錯誤的慢性源,但精心設計的鎖定允許您繞過限制。這對於COM來說是不可能的,它將始終提供線程安全性,而無需您的幫助。即使你確實想幫忙。

獲得進展的唯一方法是僅從一個線程創建和使用COM組件。該線程必須使用Thread.SetApartmentState()來初始化以選擇STA。這可以防止COM創建自己的線程爲組件尋找安全的避風港。你必須抽出一個消息循環,一個STA要求。如果您不嘗試使用來自其他線程的COM組件,並且組件本身不依賴於消息泵可用,那麼這可能會很痛苦,並且可能會被避免。這是很常見的順便說一句。當它停止響應時,您會注意到它需要一個響應,通常在預期時不會觸發一個事件。只從同一個線程對COM對象進行調用才能獲得與創建自己對象的其他線程的併發。這通常不是有用或可能的。

4

如果你的COM組件被標記爲STA (single-threaded apartment)那麼你就沒有辦法讓它成爲多線程的;組件的要求是所有對它的調用都被串行化到STA所在的線程上,並且COM自動爲你處理。這就是說,如果你的組件是一個STA組件(它看起來就是這樣),你不能將它改爲multi-threaded apartment component (MTA)甚至更​​好,因爲根本就沒有公寓之間的編組,所以因爲你不能將它改變成multi-threaded apartment component (MTA) a)它是用VB6編寫的,或者b)它是第三方的dll,那麼使用某種排隊模型可能會更好。

基本上把所有的其他工作運行的異步,然後有一個線程(或過程,它是由你),這將消耗請求調用此組件一次一個,儘可能快,因爲它可以(請注意,您可以在多個線程中實例化此組件的多個實例,您只需確保將ApartmentState property on the Thread class設置爲ApartmentState.STA),然後在調用完成時發佈事件/回調並異步繼續其他工作。

它基本上就像擁有兩個生產者/消費者實現,一個將調用分派給COM組件,另一個實現時分派結果。

1

如果每個線程的創建其自己的公寓模型對象的實例,每個線程被標記在STA中運行,那麼每個線程應該在它自己單獨的STA和你的COM對象實例應該運行在單獨的STA中。

其他的答案在這裏假設,我認爲,你的COM實例都在同一所公寓。如果調用Thread.SetApartmentState()以確保每個線程在創建COM對象實例之前都在STA中,那麼該線程的COM對象應該位於該線程的STA中,該STA與其他線程的STA分離。您不應該看到任何對不同STA中對象的調用序列化。

+0

我會告訴你最新的發現,COM DLL使用JVM連接到服務器並提交/接收請求/響應文件。如果我運行應用程序的兩個實例,遠程服務器日誌顯示創建了兩個會話,而當我在應用程序的單個實例中使用多個請求時,JVM日誌顯示請求以排隊方式提交給服務器,服務器日誌顯示只有一個會話被創建。我知道可以有一萬個理由,但專家可能會導致靶心 – EagerToLearn

+0

好吧,即使你所有的COM對象在同一個STA,並呼籲他們分別被序列化,那將不能解釋爲什麼你只有一個會話服務器。這聽起來像是你的COM對象中有邏輯管理每個進程的單個會話。 – Martin

+0

是的,它顯得那麼,當兩個應用程序實例(每個都有自己的COM引用DLL)運行時,則使用兩個交易日,而只有一個,當我們有一個實例內的多個請求(其COM參考DLL)用於 – EagerToLearn