开发者

COM ATL Threading Model or not

开发者 https://www.devze.com 2023-02-18 11:07 出处:网络
i am a little confused about COM threading models. I got a C++ COM DLL. It is defined as single apartment model:

i am a little confused about COM threading models.

I got a C++ COM DLL. It is defined as single apartment model:

_ATL_APARTMENT_THREADED

My test app is written in C# and does the following:

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

since my dll is ATL I would expect the name attribute in the DLL to be whatever any thread is setting it to.

but it looks like COM is initializing a new object for every thread that is calling it.

but I don't want that.

what am I doi开发者_JAVA百科ng wrong?

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);
...

these are only 2 values i set in the DLL (name and pass) but there are more. but the 2 threads don't write in the same object. every thread has its own object to write to.

this is how i initialize the 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());
}


You don't ever instantiate a COM object in your code. You instantiate a COM object using new on a type from an interop assembly (the one you get when you add a reference to a COM library) which calls CoCreateInstance() WinAPI function under the hood. No call to CoCreateInstance() - no threading models, so no restrictions on what threads can call what.

Please take time to read this very good explanation of COM apartments and threading.


Apartment threaded is like that - its the 'simple' model used by VB and C#. If you want to update a single object, you'll need to make your C++ dll use the Free threaded model instead, but then you are responsible for synchronisation between threads.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号