我对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());
}
答案 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模型,但是你负责线程之间的同步。