2011-03-18 59 views
1

我對COM線程模型有點困惑。COM ATL線程模型與否

我得到了一個C++ COM DLL。它被定義爲單身公寓模式:

_ATL_APARTMENT_THREADED 

我的測試應用程序是用C#編寫並執行以下操作:

start thread 1 
thread 1:setName 
start thread 2 
thread 2:setName 

,因爲我的DLL是ATL我希望在DLL name屬性無論任何線程設置它。
但它看起來像COM正在爲每個正在調用它的線程初始化一個新對象。

但我不想那樣。

我做錯了什麼?

PS: C++ DLL的StdAfx.h:

#define _ATL_APARTMENT_THREADED 

C++ DLL MyApp.cpp中:

myApp::InitInstance() { 
    CoInitialize(NULL); 
} 

C#TestApp的Program.cs:

[STAThread]<br> 
static void Main(string[] args) { 
    MyThreadClass t1 = new MyThreadClass(name1, pass1); 
    MyThreadClass t2 = new MyThreadClass(name2, pass2); 
    new Thread(new ThreadStart(t1.RunMethod)).Start(); 
    Thread.Sleep(2000); 
    new Thread(new ThreadStart(t2.RunMethod)).Start(); 

C#TestApp MyThreadClass:

public void RunMethod() { 
    ComDllWrapper.SetName(name); 
    Console.WriteLine(ComDllWrapper.GetName()); 
    Thread.Sleep(1000); 
    ComDllWrapper.SetPass(pass); 
    Console.WriteLine(ComDllWrapper.GetPass()); 
    Thread.Sleep(1000); 
    ... 
} 

C#TestApp ComDllWrapper:

[DllImport(DLLNAME)] 
public static extern void SetName(string name); 
... 

這些僅是2值I在設定DLL(名稱和傳遞),但也有更多。但2個線程不寫入同一個對象。每個線程都有自己的對象來寫入。

這是我如何初始化DLL:

C#TestApp ComDllWrapper

[DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)] 
private static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName); 

public loadWrapper(string path) { 
    var filename = Path.Combine(path, DLLNAME); 
    LoadLibrary(filename); 
    Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); 
} 
+1

顯示一些真實的代碼。 – Henrik 2011-03-18 10:32:04

+0

+1 @Henrik:Juergen,展示瞭如何初始化COM對象以及如何在線程之間共享它。通常你必須確保你的對象被正確編組。 – Andrey 2011-03-18 12:57:25

+0

你似乎沒有實例化一個COM對象 - 你只需要使用DllImport。這是沒有實際的COM - 你只是在一個調用它的線程上執行一個函數。 – sharptooth 2011-03-18 13:05:27

回答

2

你永遠不會在你的代碼中實例化一個COM對象。使用new實例化一個COM對象,該對象來自interop程序集(在添加對COM庫的引用時獲得的那個程序集)中的一個類型,該程序調用CoCreateInstance() WinAPI函數。沒有調用CoCreateInstance() - 沒有線程模型,所以沒有限制什麼線程可以調用什麼。請致電​​。

+0

感謝您的輸入。我開始 [STAThread] 靜態無效的主要(字串[] args)我的C#應用​​程序 不STAThread調用COM初始化? – 2011-03-18 14:32:02

+0

@juergen d:這不要緊,直到你實例化一個COM對象。無實例 - >成'的CoCreateInstance沒有呼叫()' - > COM子系統不踢 – sharptooth 2011-03-18 14:33:57

+0

我想這是一個愚蠢的問題:我如何instanziate COM對象在我的C#.NET代碼? – 2011-03-18 15:11:00

-1

公寓線程是這樣的 - 由VB和C#中使用它的 '簡單' 模式。如果您想更新單個對象,則需要讓C++ dll使用Free threaded模型,但是您需要負責線程之間的同步。

+0

爲什麼? STA在這裏不是問題。問題是如何在線程之間共享對象實例。它應該被封送,但我們沒有在代碼中看到它。 – Andrey 2011-03-18 12:55:27

+0

那要看他是如何創造了它,但使用FT模式會固定的,無論他的問題 - 因爲你總是得到相同的對象回來。它可能無法解決他的根本問題,但另一方面,我們不知道該解決什麼問題。 – gbjbaanb 2011-03-21 15:43:20