Модель событий

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

Рассмотрим две ранее использовавшиеся модели событий, недостатки которых устранены в более совершенной модели событий СОМ+:

- Регулярный опрос издателя. Издатель имеет интерфейс, через который подписчик может обратиться к издателю с вопросом - произошло ли заданное событие. Вопрос реализуется путем вызова некоторого метода, входные параметры которого описывают само событие, а выходные представляют ответ издателя. Данная модель имеет следующие основные недостатки: Огромная доля запросов подписчиков к издателю завершается отрицательным ответом (ожидаемое событие еще не произошло), и ресурсы и подписчика и издателя тратятся впустую. От момента реального возникновения события до того момента, как об этом событии узнает подписчик, проходит определенное время (в среднем -половина длины временного интервала между двумя последовательными опросами издателя данным подписчиком).

- Тесно-связанные события. В рамках этой модели издатель выставляет интерфейс, используя который подписчик подписывается на получение уведомлений об интересующем его событии, передавая издателю указатель на собственный интерфейс (реализованный подписчиком, но описанный издателем), через который издатель и будет уведомлять подписчика о появлении данного события. Модель тесно связанных событий устраняет упомянутые недостатки предыдущей модели, но не все. Остаются следующие вопросы: 1) Реализация. Организация подписки, рассылка уведомлений большому числу подписчиков, контроль ошибок и т.п. — сложная задача, которую следует решать не разработчику приложения. Он должен сконцентрироваться на бизнес-логике, а не на построении инфраструктуры, общей для многих приложений. 2) Фильтрация уведомлений. Подписчик получает все предназначенные ему уведомления и не может отказаться от получения некоторых из них, не отказываясь от подписки полностью. 3) Активация подписчика. Издатель получает только указатель на интерфейс подписчика, но не знает его clsid. Это означает, что подписчик все время должен находиться в активном состоянии. Издатель не сможет создать подписчика при появлении интересующего данного подписчика события.

В СОМ+ предлагается новая модель свободно –связанных событий . Идея состоит в разделении издателя и подписчика посредником, хранящим описание события и подписку на это событие. В роли посредника выступает подсистема событий (сервис операционной системы), все данные о событиях и подписках на них хранятся в СОМ+ каталоге. Подписчик подписывается на интересующие его события независимо от издателя. Издатель, при возникновении некоторого события, по умолчанию инициирует рассылку уведомлений всем подписчикам (собственно рассылка выполняется подсистемой событий). Однако он имеет возможность просмотреть подписку на данное событие и инициировать отправку уведомлений только тем подписчикам, которым пожелает. В свою очередь, подписчик может установить фильтр, ограничивающий приходящие к нему уведомления.

Издателем может выступать любой компонент (программа), имеющий право активировать экземпляр событийного класса и вызвать некоторый его метод. Никакой специальной регистрации в подсистеме событий не требуется. Для использования универсального маршалинга ( маршалинга библиотеки типов) необходимо зарегистрировать на машине издателя библиотеку типов событийного класса.

Подписчиком является обычный СОМ+ компонент, реализующий событийный интерфейс. Особенностью является его регистрация не только на той машине, где он должен быть активирован в соответствии с логикой приложения, но и на той же машине, на которой зарегистрирован событийный класс. Последнее необходимо для оформления подписки.

Существует три типа подписки:

- Постоянная

Эта подписка переживает перезагрузку компьютера. При использовании постоянной подписки при вызове некоторого метода событийного интерфейса издателем формируется новый экземпляр каждого подписчика, который обрабатывает переданный ему вызов и уничтожается после возврата из вызванного метода. Это обеспечивается тем. что подсистема событий имеет информацию о CLSID каждого подписчика и машине, на которой его следует активировать.

- Временная

Эта подписка сохраняется только на время жизни объекта - подписчика. В отличие от предыдущего случая, экземпляр класса подписчика активируется не подсистемой событий, а некоторым приложением. После этого выполняется подписка, в результате которой подсистема событий получает указатель на событийный интерфейс объекта-подписчика. После получения и обработки уведомления о событии объект-подписчик не уничтожается и может принимать новые уведомления.

- PerUser

Это вариант постоянной подписки, который можно использовать только в том случае, когда издатель и подписчик работают на одном компьютере. В записи о подписке этого типа хранится SID некоторого пользователя, в процессе которого был создан объект-подписчик. Подписка включается поде истиной событий только при входе пользователя с данным SID в систему и отключается при его выходе из системы.

Как и в случае регистрации событийного класса, зарегистрировать подписку может только администратор, используя программирование и/или Component Services. Каждая подписка на некоторое событие является объектом, хранимым в подсистеме событий. Подписаться можно на событийный интерфейс в целом (на все его методы) или на некоторый метод событийного интерфейса. Если необходимо подписаться на несколько методов событийного интерфейса (но не на все), нужно отдельно оформить подписку для каждого метода. При этом подписчик должен реализовать все методы событийного интерфейса