Статьи Королевства Дельфи

         

Два простых способа уведомления.


Раздел Подземелье Магов Алексей Еремеев ,
дата публикации 14 декабря 2000

В своей работе мне частенько приходиться делать разного рода клиент-серверные системы.
И совсем не обязательно на уровне глобальных сетей. Речь пойдет о внутренних подсистемах.
Например, имеем компонент, который эмулирует секундомер. Запустили его с параметром типа "а напомни мне, что будет полночь" и забыли. Ну и конечно событие есть типа OnAlert. И обработчик его честно будет вызван по достижении нужной нам полуночи. Но обработчик один, а захотели узнать об этом событии сразу десять разных объектов. Не вешать же десять будильников?
Конечно, проще в одном обработчике перебрать методы уведомления этих десяти объектов да и дело с концом. Но можно поступить хитрее - заставить объект-будильник самому напоминать всем кто попросит его об этом. Вот о способах такого уведомления и пойдет речь.

Как условие - объект "сервер" ничего не знает об объекте "клиенте". После некоторого размышления и перебрав несколько вариантов я пришел к выводу, что наиболее приемлимые для практики есть два способа. Первый подсмотрен в WinAPI а второй - чисто Дельфи. Оба способа основаны на простой идее регистрации клиента на сервере и оповещении сервером клиентов по внутреннему списку зарегистрированных клиентов.

Способ 1. Оповещение через механизм сообщений Windows.

в модуле объекта-сервера в интерфейсной части определяется пользовательский номер события: const WM_NOTIFY_MSG = WM_USER + 123; в объекте-сервере реализуются две интерфейсные процедуры (вкупе с объявленным в приватной секции и созданным в конструкторе TList, в деструкторе не забудем его разрушить, естественно) procedure RegisterHandle(HW: THandle); var i: integer; begin i := FWindList.IndexOf(pointer(HW)); if i < 0 then FWinList.Add(pointer(HW)); end; procedure UnregisterHandle(HW: THandle) var i: integer; begin i := FWindList.IndexOf(pointer(HW)); if i >= 0 then FWinList.Delete(i); end; и создается функция оповещения в приватной секции: procedure SendNotify(wParam, lParam: integer); var i: integer; begin i := 0; while i < FWinList.Count do begin SendMessage(integer(FWinList.Items[i]), WM_NOTIFY_MSG, wParam, lParam); Inc(i); end; end; можно вместо SendMessage использовать PostMessage, будет асинхронное сообщение, иногда это выгодней, например для исключения возможности бесконечной рекурсии.



Содержание  Назад  Вперед