Добавить в цитаты Настройки чтения

Страница 206 из 372

Для преобразования GUID в BSTR строку можно использовать функцию StringFromIID.

♦ Формируется экземпляр реализованного в системе класса с идентификатором CLSID_CEventSystem и запрашивается указатель на его интерфейс IEventSystem. Данный интерфейс предоставляет методы для добавления, удаления и извлечения событийных классов и подписок из базы данных подсистемы событий.

♦ Вызывается метод store этого интерфейса, которому в качестве первого параметра передается PROGID_EventClass, что указывает на то, что сохраняется именно событийный класс, а в качестве второго параметра передается указатель на интерфейс IEventClass экземпляра класса с идентификатором CLSID_CEventClass, параметры которого настроены на регистрируемый событийный класс.

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

♦ Асинхронность событийного класса

Если событийный класс сконфигурирован как асинхронный (Queued Component), то издатель, активируя экземпляр событийного класса как асинхронный (с помощью моникера queue), сможет не дожидаться отправки уведомлений подсистемой событий всем подписчикам, а перейти к выполнению других функций. Здесь уместно заметить, что разумно сконфигурировать как асинхронные и всех подписчиков. В этом случае подсистема событий не будет иметь проблем с подписчиками, которые должны быть активированы на машинах, к которым временно нет доступа. Кроме того, это даст возможность администратору машины, на которой активируется подписчик, управлять процессом получения уведомлений, выделяя для этого удобное время.

♦ Поддержка транзакций событийным классом

В ряде случае удобно конфигурировать и событийный класс и всех его подписчиков как поддерживающих транзакции. Тогда издатель может инициировать транзакцию, исход которой определяется всеми подписчиками.

♦ Безопасность

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

Издатель, событийный класс и подписчик могут использовать все возможности, предлагаемые системой безопасности в СОМ+. Например, подписчик может выяснить, является ли издатель события тем, за кого себя выдает.

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

♦ Параллельная рассылка уведомлений

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

Потребовав параллельную рассылку уведомлений для данного класса событий, администратор просит подсистему событий по возможности рассылать уведомления параллельно, из разных потоков.

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

♦ Идентификатор издателя





Событийному классу можно приписать уникальный идентификатор издателя. Это позволяет подписываться на события, распространение которых инициируется конкретным издателем.

Имеется еще один важный параметр класса событий, задание которого возможно только программным путем (используя административные компоненты для работы с СОМ+ каталогом) после регистрации событийного класса. Это свойство событийного класса MuitiInterfacePubiisherFilterCLSID. Данное свойство задает CLSID специального класса — фильтра, который на стороне издателя может регулировать рассылку уведомлений подписчикам. Данный фильтр будет обсуждаться позднее.

• Активация экземпляра событийного класса и инициализация рассылки уведомлений Активация экземпляра событийного класса выполняется издателем, желающим инициировать рассылку уведомлений о наступлении некоторого события. Издатель формирует экземпляр событийного класса, вызывая, например, функцию CoCreateInstance. Далее, получив указатель на событийный интерфейс данного событийного класса, он вызывает некоторый метод этого интерфейса, инициируя тем самым рассылку уведомлений всем подписчикам. Особенностью процесса активации экземпляра событийного класса является то, что подсистема событий автоматически синтезирует реализацию событийного интерфейса, обеспечивая активацию подписчиков и вызов соответствующего реализованного каждым подписчиком метода событийного интерфейса. Заметим, что в процесс рассылки уведомлений могут вмешаться два фильтра — фильтр со стороны издателя и фильтр со стороны подписчика.

Если не использовалась технология асинхронных компонент, и издатель дождался конца процесса рассылки уведомлений, то он может проанализировать код возврата типа hresult, который может принимать одно из следующих значений:

♦ S_SUCCESS — уведомления были доставлены всем подписчикам,

♦ EVENT_S_SOME_SUBSCRIBERS_FAILD — код успешного в целом завершения рассылки, однако доставка уведомлений некоторым подписчикам завершилась неудачей. Заметим, что на этом этапе невозможно определить подписчиков, не получивших уведомлений,

♦ EVENT_E_ALL_SUBSCRIBERS_FAILD — неудача, никто из подписчиков не получил уведомления.

♦ EVENT_S_NOSUBSCRIBERS — операция завершилась успехом, но подписчики на данное событие отсутствуют.

Издатель, подписчик и подписка

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

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

По поводу подписки следует заметить, что существует три ее типа:

• Постоянная

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

• Временная

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