2013-09-24 58 views
0

我閱讀了關於公寓模型的內容,但當我試圖瞭解以下內容時,它仍然讓我感到困惑:誰的公寓決定了公寓模式?它是線程的公寓還是創建對象的公寓?
考慮以下情形:對象公寓vs線程公寓

  1. 我已經創建了一個只有一個接口,它是ISimpleCom C++ ATL COM DLL,我有一個類,接口,只有一個方法test(); 該類公開農具從設置STA公寓的CComObjectRootEx<CComSingleThreadModel>繼承。

  2. 在C#WinForms項目中引用此DLL,並在MTA線程(而不是UI線程)上創建SimpleCom對象。 現在的問題是: 可以說這個對象上的UI線程調用test(),它會被封送到線程創建的對象還是會在UI線程上執行?

    • 如果它跟在對象COM單元之後,則應將此調用封送到創建對象的線程,因爲它是STA對象。
    • 如果它跟隨創建MTA的線程單元,它應該在UI線程上執行。

哪一個是正確的?

回答

2

簡單的規則:

  • 線程可能是零或一個公寓成員
  • 單線程公寓(STA)由單個線程的,MTA - 一個或多個線程的,但可以有在每個進程的至多一個MTA
  • 線程在其COM初始化

所以一段代碼要麼在STA(在STA線程),或在MTA執行,或者t時刻「加入」公寓尚未使用COM初始化hread。當您通過COM實例化一個對象時,COM會將公寓模型與從中調用API的公寓類型相匹配。

此類公開從CComObjectRootEx繼承,它設置STA公寓。

不,這與設置公寓模式無關。 CComSingleThreadModel說,這個類是使用簡單的基礎,這是很好的在STA中運行的對象 - 特別是當它涉及到的訪問對象的引用計數,因爲假設類爲單線程內住它不會使用InterlockedXxx API或關鍵部分。這確實設置了COM類的公寓模型,它並不表示這個類將在STA上運行,這只是提供了合適的基類。

ATL COM DLL託管類的公寓模型將顯示在與COM類關聯的.RGS文件上,並將與DLL註冊合併到註冊表中。如果這是「公寓」模型,那麼...

在MTA線程(而不是UI線程)上創建SimpleCom對象。

... COM將看到它不能直接在調用線程上實例化,因爲該線程屬於MTA。所以COM將在工作者STA線程上實例化,並將創建一個代理/存根對以將所請求的接口綁定到調用方MTA中。

+0

因此,如果我理解正確,從我在後文中描述的場景中,UI線程和創建類的MTA線程都不會執行test()。 test()的執行會被封送到創建了哪個COM類的工作線程中,並且在哪個線程中? – JobNick

+0

它不會在MTA線程上執行。該調用將被封送到工作人員,或者如果它是STA線程,則將其封裝到UI線程中。然後,實際的方法將從那裏執行。 –

+0

爲了避免混淆,可以使用以下線程:1-UI,2-MTA,3-Worker。所以COM對象是在線程#2上創建的,但因爲它是MTA線程,所以它創建了新的線程ID爲3的STA工作線程。現在,UI線程#1將調用COM#的對象test()方法,將您的回覆test()封送到線程#3並由該線程執行? – JobNick