Каков предпочтительный способ уведомления серверного кода несколькими клиентами об изменениях данных в одном приложении Delphi? - PullRequest
21 голосов
/ 27 февраля 2012

У меня есть большое приложение Delphi, в котором есть основной «серверный» код, содержащий мои данные.В одном и том же приложении «клиент» пользователь может открывать и закрывать несколько немодальных «клиентских» форм для проверки этих данных.Изменения данных делятся на два типа - основные (например, структурные изменения, такие как данные были добавлены или удалены) и второстепенные, такие как изменение значения данных.Существующие открытые клиентские формы должны обновляться для отображения измененных данных в кратчайшие сроки.Это не база данных, мой «сервер» использует мои собственные структуры данных, поэтому мои решения могли упустить, возможно, стандартные методы, доступные в рамках официальной структуры базы данных.Тем не менее, я повторял свои решения так много раз, что решил спросить, есть ли формальные методы и, возможно, компоненты Delphi, которые улучшат или упростят мой код.Я собираюсь перейти к многопоточному коду, который делает вопрос еще более актуальным для меня.

Я использую два метода:

  1. Отметка времени.Код 'server' поддерживает значение Int64, полученное из QueryPerformanceCounter.Клиентские формы проверяют это значение на таймере 300 мс и обновляются, если их копия метки времени отличается от копии сервера.Я полагаю, что это мое решение «тянуть».

  2. Уведомление интерфейсаКод «сервера» поддерживает класс, унаследованный от TInterfaceList с помощью методов AddClient и RemoveClient, которые регистрируют простой общий интерфейс уведомлений клиента.Каждый из клиентов регистрируется в этом списке при создании и отменяет регистрацию при уничтожении.Изменения данных на сервере вызывают итерацию по этому списку, вызывая каждого клиента, чтобы сообщить ему об изменениях.Полагаю, это мое решение «push».

Мне нравятся интерфейсы, и решение 2 кажется хорошим, поскольку оно избегает тиковых таймеров и легко отлаживается (хотя вызовы отмены регистрации могут быть проблематичными в порядкеразрушение).Также есть потенциальные последствия для производительности, потому что вполне вероятно, что в секунду могут происходить тысячи изменений данных, и я должен быть осторожен, чтобы использовать механизм BeginUpdate / EndUpdate для преобразования моих многочисленных изменений данных на сервере в один фактический вызов уведомления.В конечном итоге мне понадобился какой-то таймер, чтобы объединить вызовы в одно аккуратное обновление отображаемой формы.

Хотя оба решения работают прекрасно, и я разрываюсь между ними.Для многопоточного решения я уверен, что есть и другие подводные камни, о которых я ничего не знаю.Любые замечания будут оценены.Я использую XE2.

Ответы [ 2 ]

8 голосов
/ 27 февраля 2012

Вы должны принять во внимание то, что вы хотите, чтобы произошло, когда число клиентов растет, а затем выбрать между двумя пороками:

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

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

Я бы реализовал Шаблон наблюдателя в Delphi, используя интерфейсы, вы могли бы использовать это или это в качестве начала.

1 голос
/ 29 февраля 2012

A использовал Windows API для решения проблемы, подобной этой. Но я считаю, что мой подход проще. В моем заявлении я не знал количество «клиентов» и какие формы на самом деле клиенты.

То, что я сделал, это:

  1. Передача сообщения Windows на все формы, открытые моим приложением (screen.forms[X]). Сообщение включает в WParam указатель к записи, которая содержит информацию о событии. Также, различные действия транслируют разные сообщения. WM_RECORDUPDATE для обновления БД, например.

  2. Windows (клиенты) прослушивают сообщения в виде:

    procedure RecordUpdateMessage(var msg: TMessage); message WM_RECORDUPDATE;

Процедура RecordUpdateMessage прочитать запись, указанную msg.WParam и на основе данных в записи определяет, реагировать ли на обновление, вставку или удаление записи в БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...