COM ATL线程模型与否

时间:2011-03-18 10:26:14

标签: c++ multithreading com atl

我对COM线程模型有点困惑。

我有一个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);
...

这些只是我在DLL(名称和传递)中设置的2个值,但还有更多。但是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());
}

2 个答案:

答案 0 :(得分:2)

您不会在代码中实例化COM对象。您可以使用new在互操作程序集(您在添加对COM库的引用时获得的类型)上的类型实例化COM对象,该文件在引擎盖下调用CoCreateInstance() WinAPI函数。没有调用CoCreateInstance() - 没有线程模型,因此对线程可以调用什么没有限制。

请花点时间阅读this very good explanation of COM apartments and threading

答案 1 :(得分:-1)

单元线程就是这样 - 它是VB和C#使用的'简单'模型。如果你想更新一个对象,你需要让你的C ++ dll使用Free thread模型,但是你负责线程之间的同步。