2011-03-18 81 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