Модель потоков AT COM или нет - PullRequest
1 голос
/ 18 марта 2011

Я немного запутался в моделях COM-потоков.

Я получил C ++ COM DLL. Он определяется как модель одной квартиры:

_ATL_APARTMENT_THREADED

Мое тестовое приложение написано на C # и выполняет следующие действия:

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

, поскольку моя dll - ATL, я ожидал бы, что атрибут имени в DLL будет таким, каким его устанавливает любой поток.
но похоже, что 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 значения, которые я установил в 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());
}

Ответы [ 2 ]

2 голосов
/ 18 марта 2011

Вы никогда не создаете экземпляр COM-объекта в своем коде. Вы создаете экземпляр COM-объекта, используя new для типа из сборки взаимодействия (тот, который вы получаете, когда добавляете ссылку на библиотеку COM), который вызывает скрытую функцию CoCreateInstance() WinAPI. Нет вызова CoCreateInstance() - нет моделей потоков, поэтому нет ограничений на то, что потоки могут вызывать как.

Пожалуйста, найдите время, чтобы прочитать это очень хорошее объяснение COM-квартир и потоков .

0 голосов
/ 18 марта 2011

Квартира с такой резьбой - это «простая» модель, используемая VB и C #.Если вы хотите обновить один объект, вам нужно будет заставить dll C ++ использовать вместо него модель Free Threading, но тогда вы отвечаете за синхронизацию между потоками.

...