потоки и COM
От: Аноним  
Дата: 13.08.03 12:14
Оценка:
Народ. У меня такой трабл:
есть два процесса:
в первом есть один COM объект A
во втором два COM объекта B , C

Объекты B и C исполняются в разных потоках.
Объект B получает указатель на объект A.
Я передаю его в объект C, после чего пытаюсь запросить нужный мне интерфейс и вызвать метод. Мне выдают ошибку связанную с маршалингом. Как это обойти?
Re: потоки и COM
От: UnrealAlex Россия  
Дата: 13.08.03 12:29
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Народ. У меня такой трабл:

А>есть два процесса:
А>в первом есть один COM объект A
А>во втором два COM объекта B , C

А>Объекты B и C исполняются в разных потоках.

А>Объект B получает указатель на объект A.
А>Я передаю его в объект C, после чего пытаюсь запросить нужный мне интерфейс и вызвать метод. Мне выдают ошибку связанную с маршалингом. Как это обойти?
Объект B получает на самом деле прокси интерфейса объекта A. Пытаясь вызвать метод из другого потока прокся возврящяет ошибку.
Возможно 2 варианта
1. Использовать неявный маршалинг, т. е. передать интерфейс объекту C их объекта B через метод, но в этом случае объект B должен держать отмаршалированную ссылку на объект С.
2. Использовать GIT
3. Использовать апи-функции CoMarshalInterface, CoUnmarshalInterface

NB! Поскольку ты будешь маршалить прокси нужно учесть 2 вещи
1. Апартамент в котором живет объект B должен жить до тех пор пока ты не отпустишь ссылку из объекта C на объект A
2. Если захочешь несколько раз размаршаливать, то нельзя использовать CoMarshalInterface с параметром MSHLFLAGS_TABLESTRONG он не умеет маршалить прокси — придеться воспользоватьмя GIT-ом
Невозможное мы сделаем сегодня — чудо займет немного больше времени. /Аноним/
Re[2]: потоки и COM
От: x2004  
Дата: 13.08.03 13:06
Оценка:
Здравствуйте, UnrealAlex, Вы писали:

UA>Здравствуйте, <Аноним>, Вы писали:


А>>Народ. У меня такой трабл:

А>>есть два процесса:
А>>в первом есть один COM объект A
А>>во втором два COM объекта B , C

А>>Объекты B и C исполняются в разных потоках.

А>>Объект B получает указатель на объект A.
А>>Я передаю его в объект C, после чего пытаюсь запросить нужный мне интерфейс и вызвать метод. Мне выдают ошибку связанную с маршалингом. Как это обойти?
UA>Объект B получает на самом деле прокси интерфейса объекта A. Пытаясь вызвать метод из другого потока прокся возврящяет ошибку.
UA>Возможно 2 варианта
UA>1. Использовать неявный маршалинг, т. е. передать интерфейс объекту C их объекта B через метод, но в этом случае объект B должен держать отмаршалированную ссылку на объект С.
UA>2. Использовать GIT
UA>3. Использовать апи-функции CoMarshalInterface, CoUnmarshalInterface

UA>NB! Поскольку ты будешь маршалить прокси нужно учесть 2 вещи

UA>1. Апартамент в котором живет объект B должен жить до тех пор пока ты не отпустишь ссылку из объекта C на объект A
UA>2. Если захочешь несколько раз размаршаливать, то нельзя использовать CoMarshalInterface с параметром MSHLFLAGS_TABLESTRONG он не умеет маршалить прокси — придеться воспользоватьмя GIT-ом

Функции объекта A требуются в обработчике асинхронного вызова в объекте B.
Асинхронный вызов проходит очень часто. Если не сложно, что мне выбрать конкретнее?
Re[3]: потоки и COM
От: UnrealAlex Россия  
Дата: 13.08.03 13:12
Оценка:
Здравствуйте, x2004, Вы писали:

X>Функции объекта A требуются в обработчике асинхронного вызова в объекте B.

X>Асинхронный вызов проходит очень часто. Если не сложно, что мне выбрать конкретнее?
Немного не понял. Изначально стояла проблема с объектом С! Что еть в твоем понимании асинхронный вызов? PostMessage? APC?
Можешь описать проблему более подробно.
Невозможное мы сделаем сегодня — чудо займет немного больше времени. /Аноним/
Re[4]: потоки и COM
От: x2004  
Дата: 13.08.03 13:22
Оценка:
Здравствуйте, UnrealAlex, Вы писали:

UA>Здравствуйте, x2004, Вы писали:


X>>Функции объекта A требуются в обработчике асинхронного вызова в объекте B.

X>>Асинхронный вызов проходит очень часто. Если не сложно, что мне выбрать конкретнее?
UA>Немного не понял. Изначально стояла проблема с объектом С! Что еть в твоем понимании асинхронный вызов? PostMessage? APC?
UA>Можешь описать проблему более подробно.

Честно говоря все равно где... в B или в C
Объекты B и C содержат в себе функцию, которая осуществляет асинхронный вызов APC

QueueUserAPC(ApcFunc,hThread,dwParam);

В ApcFunc требуется вызвать методы A, Сама ApcFunc исполняется в ином потоке, чем родительский класс — hThread.
Интерфейс A передается в поток родительского класса (B или C). Но когда пытаешься пользоваться ею в потоке hThread — абзац... Ошибка маршалинга. QueueUserAPC я зову достаточно часто и вызов методов А (и видимо маршалинг демаршалинг) мне нужно производить очень часто...
Re[5]: потоки и COM
От: UnrealAlex Россия  
Дата: 13.08.03 13:47
Оценка: 10 (1)
Здравствуйте, x2004, Вы писали:

UA>>Здравствуйте, x2004, Вы писали:

X>Честно говоря все равно где... в B или в C
X>Объекты B и C содержат в себе функцию, которая осуществляет асинхронный вызов APC

X>QueueUserAPC(ApcFunc,hThread,dwParam);


X>В ApcFunc требуется вызвать методы A, Сама ApcFunc исполняется в ином потоке, чем родительский класс — hThread.

X>Интерфейс A передается в поток родительского класса (B или C). Но когда пытаешься пользоваться ею в потоке hThread — абзац... Ошибка маршалинга. QueueUserAPC я зову достаточно часто и вызов методов А (и видимо маршалинг демаршалинг) мне нужно производить очень часто...

Тогда используй GIT (проверка ошибок опущена для наглядности)
1. Получаешь интерфейс на объект A
2. Кладешь его в GIT

CComPtr<IA> pIA;
CComPtr<IGlobalInterfaceTable> ptrGIT;

pIA.CoCreateInstance(CLSID_A);
ptrGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable);

DWORD dwCookie = 0;
ptrGIT->RegisterInterfaceInGlobal(pIA, __uuidof(pIA), &dwCookie);


3. В APC функции

::CoInitializeEx(0, COINIT_MULTITHREADED); // если в этом потоке не было вызвано ранее

CComPtr<IA> pIA;
CComPtr<IGlobalInterfaceTable> ptrGIT;

pIA.CoCreateInstance(CLSID_A);
ptrGIT.CoCreateInstance(CLSID_StdGlobalInterfaceTable);

ptrGIT->GetInterfaceFromGlobal(dwCookie, __uuidof(pIA), reinterpret_cast<void**>(&pIA));

pIA = NULL;
::CoUninitialize(); // если вызвал в начале ::CoInitializeEx(0, COINIT_MULTITHREADED)


З.Ы.
1. не забудь вызвать RevokeInterfaceFromGlobal
2. как я уже говорил — раз ты маршалишь прокси надо обеспечить жизнь апартамента, в котором она была замаршалена до вызова RevokeInterfaceFromGlobal
3. Не забудь определить макрос _WIN32_DCOM перед включением objbase.h
Невозможное мы сделаем сегодня — чудо займет немного больше времени. /Аноним/
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.