2011-06-06 72 views
2

嗨,我是COM的初學者。我想在STA和MTA模式下測試一個COM DLL。我的第一個問題是:是否有可能COM對象支持STA和MTA?關於COM多線程和STA/MTA的問題

現在我想下面的STA代碼片段:

// this is the main thread 
m_IFoo; 
CoInitializeEx(STA); // initialize COM in main thread 
CreateInstance(m_IFoo); 
m_IFoo->Bar(); 

CreateThread(ThreadA); 
// start ThreadA 

// this is secondary thread 
ThreadA() 
{ 
    CoInitializeEx(STA); 
    m_IFoo->Buz(); // call m_IFoo's method directly 
} 

請問此代碼的工作?我錯過了任何基本的東西?我知道主線程需要一個窗口消息循環來執行其他線程的調用。我必須做任何事嗎?

現在我繼續測試MTA。如果我只是用上面的代碼中的「MTA」替換「STA」,它會起作用嗎?

另一個問題是:由於GUI的線程必須是STA,我無法在GUI線程中初始化和測試MTA?

在此先感謝和遺憾,對我來說是對COM和線程天真。

回答

2

能夠從「MTA」到「STA」開關和開關等造成的後果將取決於對象是如何在系統註冊表中註冊。爲了使對象「支持」兩種情況而不進行編組,必須將ThreadingModel設置爲Both

請參閱this great answer - Both意思是「要麼是Free要麼是Apartment,這取決於調用者如何初始化COM」。這正是你想要的。

至於使用「STA」模式 - 是的,踩的對象屬於必須通過呼叫GetMessage()TranslateMesage()DispatchMessage()循環運行消息循環。無論如何,對象方法不會直接從第二個線程調用 - 它們將通過代理。詳細解釋請參見this very good article

3

您的代碼是不合法的COM,因爲你是直接從一個STA指針傳遞到另一個,這COM不允許。

在COM中,接口指針具有「公寓親和力」,它們只能被一個公寓內使用。要將一個指針從一個STA傳遞到另一個STA,或者在STA和MTA之間傳遞指針,您必須「編組」指向安全表示,然後由接收線程解組。

要做到這一點,最簡單的方法是使用Global Interface Table;你在一個線程中使用它註冊接口並獲取一個DWORD,然後在另一個線程中使用該DWORD來獲取另一個線程可以使用的接口版本。

如果兩個線程都是MTA,則可以避免這樣做。雖然STA是每個線程一個 - 每個STA線程都有自己的aparment - MTA由所有MTA線程共享。這意味着MTA線程可以自由地在它們之間傳遞COM指針。 (但是他們仍然需要編組,如果通過指針或STA線程。)

一般來說,你不STA或MTA之間更改代碼,你通常在一開始就立刻把它決定這一點。如果線程有UI,那麼它需要一個消息循環,並且通常是STA。如果沒有UI,您可以決定使用MTA。但是一旦你做出了這個決定並且編寫了你的​​代碼,那麼以後很難再轉換到另一個,因爲選擇一個或者另一個有不同的需求和假設,會影響代碼;從STA更改爲MTA或反之亦然,您必須仔細查看代碼並查看是否需要更改指針分配等內容。