Re[18]: Вызов событий COM из разных потоков
От: Аркадий Россия  
Дата: 26.11.09 14:55
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Остаётся не прояснённым вопрос, откуда берётся внезапно объявившийся IUpEvents :) Кто его реализует, как Вы его получаете, ну и тд, всё то-же, что уже спрашивалось про IMyEvent. Нужен ли для него маршаллинг, зависит от этого. А так — да, если все объекты созданы в одном апартаменте, и этот апартамент не противоречит их потоковой модели, то всё должно работать напрямую.

IUpEvent объявлен уже в ..._TLB.h следующим образом:
interface DECLSPEC_UUID("{3D382A6F-126C-486D-AB6F-B45C09D55667}") IUpTaskEvents;

interface IUpTaskEvents : public TDispWrapper<IDispatch>
{
  HRESULT __fastcall OnMessage(Upiterobj_tlb::IMessage* Message/*[in]*/)
  {
    _TDispID _dispid(/* OnMessage */ DISPID(5));
    TAutoArgs<1> _args;
    _args[1] = (LPDISPATCH)(Upiterobj_tlb::IMessage*)Message /*[VT_USERDEFINED:1]*/;
    return OleFunction(_dispid, _args);
  }
};

Я его получаю при создании объекта (Up) через Wizard Builder-а, указав, что объекту нужны события.
Так выглядит автоматически создаваемая при этом голова объекта Up:
class ATL_NO_VTABLE TUpImpl : 
  public CComObjectRootEx<CComMultiThreadModel>,
  public CComCoClass<TUpImpl, &CLSID_Up>,
  public IConnectionPointContainerImpl<TUpImpl>,
 // public TEvents_Up<TUpImpl>,
  public TEventsWrapper<TUpTaskImpl>,
  public IDispatchImpl<IUpTask, &IID_IUpTask, &LIBID_UpiterObj>
{

Замечу при этом, что TEvents_Up — это обертка интерфейса, позволяющая "дергать" методы интерфейса, который реализовал клиент и передал через advise(...). Я её переписал с использованием GIT, назвал TEventsWrapper. Работает так же, только сохраняет подключившиеся интерфейсы в GIT, а не в свой массив интерфейсов, это должно было помочь вызывать событие из другого потока, но не помогло.

М>Дело в том, что так — "дебаггер проходит по телу Fire_OnMessage и не дает никакого результата" — просто не бывает. Если вызов метода реально присутствует в скомпилённом коде, и выполнение до него доходит, то метод просто физически не может быть не вызван. А вот что происходит внутри этого метода, это уже другой вопрос. Может там что-нибудь типа
М>

М>if (GetCurrentThreadId() != InitThreadId) return 0;
М>

М>вот и получится, что при вызове этого метода из "неправильного" потока "ничего не происходит". Ну и определённая разница может быть от того, вызываете ли Вы метод самого объекта, или-же Ваш код имеет дело с прокси.

Да, но доступ до тела Fire_OnMessage у меня есть, и я по нему "хожу" дебаггером и смотрю, что по всем своим вызовам он проходится. Один из вызовов в Fire_OnMessage — это OnMessage() интерфейса IUpEvents, который отрабатывается, не давая никакой реакции. Но доступа до тела IUpEvents у меня нет, т.к. он передавался от клиента, через advise().

При этом если Fire_OnMessage выполняется в основном потоке сервера, то OnMessage интерфейса IUpEvents отрабатывается.
С уважением, Аркадий.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.