Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вызов метода DLL COM сервера в разных потоках клие, сервер на ATL 
:(
    Опции темы
Андреy
Дата 19.3.2009, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 9.4.2008

Репутация: нет
Всего: нет



Добрый день. Помогите пожалуйста прояснить ситуацию.
Задача следующая: клиент может создавать несколько потоков, в котором будут вызываться методы DLL COM сервера (в частном случае, один итот же метод).
Почитав статьи про апартаменты и все дела, поначалу реализовал сервер с моделью потоков apartment, и решил, что все будет ОК. К тому же нижеприведенный код работает (как выяснилось, лишь иногда). Сервер написан на ATL+MFC
Процедура, выполняющаяся в очередном потоке (клиент на Delphi, но не суть):
Код

CoInitialize(nil);

  // Подключение драйвера устройства 
  try
    pDriver := CreateComObject(ProgIdToClassId('APLC.DataTransporter')
                                 ) as IAplcDataTransporter;
  except
    on E: Exception do begin
      //...
    end;
  end;
  Log('ID потока опроса: ' + IntToStr(ThreadID));  // запись в лог ИД запускающего потока
  if pDriver <> nil then  
  try
    pDriver.GetDataViaLAN(FServerPort, FServerAddress)
  except
      // выдаем последнюю ошибку, установленную драйвером
      LogException(SysErrorMessage(GetLastError())
                     );
      pDriver := nil;
  end;

Рассуждения были следующие (неправильные): 1-ый запущенный поток загружает DLL сервера и создает экземпляр COM объекта, 2-ой запущенный поток создает новый экземпляр СОМ объекта. Сам COM объект содержит только инкапсулированные данные, глобальных переменных нет. 
Одно время наблюдал успешный параллельный вызов методов в разных потоках (читались данные с устройств по локальной сети, путаницы не было, данные поступали от каждого девайса свои).
Но я не замечал следующих проблем:
1. Иногда 1 поток при попытке создания COM объекта выдает ошибку "Class already exists" (см. LogException(SysErrorMessage(GetLastError())). При этом это получается не ошибка, установленная внутри вызова метода (я не устанавливаю там такой код), это система выдает, уже после.
2. Еще момент — внутри кода метода сервера я отслеживаю ID потока, в котором выполняется метод. Имею следующее: клиент создает 2 потока, в обоих потоках выполняется метод, и он записывает в лог ID лишь одного процесса.
3. Метод при работе записывает в лог ход процесса — так вот иногда 1 поток записывал все, а 2-ой — не все (значит, он 1-ый перекрывал работу 2-го).

Я поменял потоковую модель — сделал Both. Результат: в лог теперь пишется все, но вот ID процесса по-прежнему один и тот же. Но ведь по идее в каждом потоке создан отдельный экземпляр COM объекта.

В общем, как делаются такие DLL COM сервера (приложение-клиент хочет одновременно в разных потоках запускать метод на выполнение)? 
PM MAIL   Вверх
jonie
Дата 24.3.2009, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 5
Всего: 118



апартаменты... 
вот у меня есть очень хорошая дока по ним. мб она не поможет вам, но внесет ясность однозначно.

Присоединённый файл ( Кол-во скачиваний: 16 )
Присоединённый файл  ______________________________COM_________________________Delphi.rar 29,24 Kb


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
jonie
Дата 25.3.2009, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 5
Всего: 118



Итак, если у вас STA СЕРВЕР, то вы объявили неправильно клиента: нужно объявить его как MTA (CoInitializeEx(0, COINIT_MULTITHREADED) вывать) (если вы вызываете метод одного объекта клиента в разных потоках без маршалинга).


Если ваш сервер STA и, метод одного объекта  вызывается из разных потоков без явного маршалинга (передачей туда указателя), то вызовы будут идти в разных потоках (по сути своей это прямой вызов из потока метода по указателю, без каки-либо прокси объектов). Нужно уведомлять систему COM о таких намерениях - делая маршалинг.

.....

Это сообщение отредактировал(а) jonie - 25.3.2009, 00:23


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: COM/DCOM/ActiveX/ATL/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0812 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.