Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

COM+ Events в пользовательском потоке

1.8K
25 февраля 2009 года
Arkady
153 / / 18.12.2007
Задача:
Как реализовывать события COM сервера, происходящие в основном его потоке, прекрасно разобрано в FAQ этого раздела форума.

Необходимо же, чтобы сервер запускал второй поток, в котором бы срабатывал механизм событий. Однако в другом потоке этот механизм уже не работает (т.е. Fire_Event просто не отрабатывает, клиент, подключающийся к этим событиям о них не узнает, хотя тот же Fire_Event в основном потоке сервера ловится клиентом).

Т.е. вопрос - как заставить сервер реализовывать (или VBA клиент цепляться) не только к событиям основного потока сервера, но и к событиям в дополнительных потоках.
Как правильно реализовать это на сервере?

Очень надеюсь на помощь, заранее спасибо :-)
7.3K
26 февраля 2009 года
H010d Freeze
143 / / 08.08.2006
Бился над аналогичной проблемой при разработке ActiveX контролов.
Единственное решение, которое нашел - инициация событий в контексте основного потока.
Рабочий поток делает PostMessage в основной поток и ждет сигнала, основной поток делает Fire_Event и устанавливает сигнал, рабочий поток продолжает работу.
1.8K
04 марта 2009 года
Arkady
153 / / 18.12.2007
Цитата: H010d Freeze
Бился над аналогичной проблемой при разработке ActiveX контролов.
Единственное решение, которое нашел - инициация событий в контексте основного потока.
Рабочий поток делает PostMessage в основной поток и ждет сигнала, основной поток делает Fire_Event и устанавливает сигнал, рабочий поток продолжает работу.


Да, интернет говорить, что есть 2 варианта решения, через PostMessage и через CoMarshalInterThreadInterfaceInStream.

1) Вариант через CoMarshalInterThreadInterfaceInStream у меня не получается реализовать, потому что Automation Object, автоматически создаваемый Builder-ом на самом деле имеет Pure Function AddRef(), т.е. IUnknown у него состоит из абстрактных методов. И передать указатель на этот класс, соответственно, не удается (на этапе выполнения Windows шлет ошибку "Call pure function". Да и при попытке создать экземпляр себя не компилится, поскольку AddRef() = 0. Т.е. я так понимаю, именно на этой функции CoMarshalInterThreadInterfaceInStream и "запарывается").

2) Вариант через PostMessage, честно говоря, не понимаю, как реализовать, ведь я не управляю основным потоком и не понимаю, как сказать ему ловить сообщения. Всё, что я знаю об основном потоке, это то, что в нем выполняются методы Automation Object, которые я пишу.

(!!) Заставлять его зависать и ждать сообщения от второго потока я не могу, тогда теряется смысл во втором потоке. А вот как реализовать так, чтобы пользователь мог работать с сервером, а через час работы сервера второй поток послал ему PostMessage и сервер его бы сразу поймать - не понимаю.
Если Вы подскажете, как Вы это сделали, Вы мне очень поможете =)
Заранее спасибо =)

1.8K
04 марта 2009 года
Arkady
153 / / 18.12.2007
Есть идея как-то внедриться в обработчик входящих сообщений, но я не представляю как сделать это в случае с COM/ActiveX =(
Кто-нибудь имеет опыт проделывания этого? :)
7.3K
05 марта 2009 года
H010d Freeze
143 / / 08.08.2006
См. пример:
[ATTACH]3395[/ATTACH]

Это частное решение подходящее для ActiveX-контролов. Но может оно натолкнет на мысли и по Вашей проблеме :)
1.8K
19 октября 2009 года
Arkady
153 / / 18.12.2007
Цитата: H010d Freeze
См. пример:
[ATTACH]3395[/ATTACH]

Это частное решение подходящее для ActiveX-контролов. Но может оно натолкнет на мысли и по Вашей проблеме :)



Пример интересный, но в нем нехватает файлов. Из того, что я понял - там создается второй поток, который имеет искусственные задержки (5 секунд). Т.е. каждые пять секунд он просто делает проверку.

Но что если сообщения будут сыпаться с частотой бОльшей, чем раз в 5 секунд? Хочется же именно слушающего потока, который бы давал событие.

1.8K
19 октября 2009 года
Arkady
153 / / 18.12.2007
Добрый день, ситуация осталась той же, нужно дергать события объекта из второго потока сервера. Никак не могу разобраться, как этого добиться.

Ситуация следующая:
Есть Сервер. Exe. Он динамически линкуется к dll. Эта dll содержит интерфейс такого класса:
Код:
interface IShowClass
{
public:
    virtual void Init(IMyEvents* Ev) = 0;
    virtual void Start() = 0;
    virtual void Stop() = 0;
};

class T_showclass : public IShowClass
{
//...
public:
    virtual void Init(IMyEvents* Ev);
    virtual void Start();
    virtual void Stop();

};

Т.е. dll возвращается указатель на интерфейс объекта. После выполнения метода Start() этого интерфейса, там внутри создаются потоки, идет сложная работа, а в некоторые ключевые моменты дергаются методы интерфейса IMyEvent, указатель на который должен быть передан в объект извне.
Т.е. пользователь извне реализует класс, наследник от IMyEvent, где реализует все методы IMyEvent (реакции на все события объекта IShowClass), передает в IShowClass указатель на свой экземпляр, приведенный к типу IMyEvent, потом запускает этот объект и объект в нужных местах вызывает методы интерфейса IMyEvent, а значит код, реализованный пользователем.
Так самодельно реализована модель событий. Такова dll (объяснил, чтобы понимать, в чем дело).

Эту dll использует Automation Object (COM), у которого есть методы и события.
Такие
Код:
class ATL_NO_VTABLE TUpTaskImpl :
  public CComObjectRootEx<CComMultiThreadModel>,
  public CComCoClass<TUpTaskImpl, &CLSID_UpTask>,
  public IConnectionPointContainerImpl<TUpTaskImpl>,
  public TEvents_UpTask<TUpTaskImpl>,
  public IDispatchImpl<IUpTask, &IID_IUpTask, &LIBID_UpiterObj>
{
//...
public:
  STDMETHOD(Start());
  STDMETHOD(Stop());
};

Соответственно надо, чтобы события этого сервера реагировали на события из DLL. Однако события в DLL - "происходят" не в основном потоке программы, а во внутренних потоках DLL, а потому даже если я туда передаю пользовательскую реализацию IMyEvent, которая оборачивает вызовы событий TUpTaskImpl, эти события не видятся из VBA.
А очень надо, чтобы виделись.

CoMarshalInterThreadInterfaceInStream и обратная - почему-то не отрабатывают.
Может быть кто-то решал такую проблему?
7.3K
19 октября 2009 года
H010d Freeze
143 / / 08.08.2006
Цитата:

Пример интересный, но в нем нехватает файлов.



Хм. Все файлы на месте. Все должно компилиться и работать.

Цитата:

Из того, что я понял - там создается второй поток, который имеет искусственные задержки (5 секунд). Т.е. каждые пять секунд он просто делает проверку.


Это имитация асинхронного события вставки карты в устройство для чтения карточек. Задержка задается свойством Delay.
5 сек компонент TFakeReader ждет, чтобы слушатель отложенного уведомления забрал из очереди сообщение, т.е. обработал асинхронное событие - это синхронизация источника события и слушателя. Ибо асинхронное событие для моей задачи должно обрабатываться синхронно =)

Цитата:

Но что если сообщения будут сыпаться с частотой бОльшей, чем раз в 5 секунд? Хочется же именно слушающего потока, который бы давал событие.


Что Вас смущает?
Про слушающий поток дающий событие совсем непонятно.

1.8K
19 октября 2009 года
Arkady
153 / / 18.12.2007
Цитата: H010d Freeze
Хм. Все файлы на месте. Все должно компилиться и работать.


У меня .bpr овского файла не хватает для второго проекта (который, судя по всему, dll).
Но так - пример полезный и понятный, мне помог, спасибо.

7.3K
19 октября 2009 года
H010d Freeze
143 / / 08.08.2006
Цитата:

У меня .bpr овского файла не хватает для второго проекта (который, судя по всему, dll).




FakeReaderExample_CB6.bpk - это проект для run-time пакета
dclFakeReaderExample_CB6.bpk - это проект для design-time пакета
AXAsyncExample_CB6.bpr - это проект для ActiveX Library

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог