Обратный вызов Delphi datasnap — широковещательный вопрос

#delphi #callback #datasnap #podo

#delphi #обратный вызов #datasnap #podo

Вопрос:

Я снова нахожусь в ситуации, когда я трачу неприличное количество времени на попытки настроить образцы обратного вызова datasnap в соответствии со своими потребностями. Я ООП-программист старой школы, и у меня есть несколько очень больших иерархий объектов в стиле PODO «toolbox» 🙂 .. и, имея эту замечательную функцию datasnap, я хочу использовать возможности обратного вызова.

НО — когда я это реализую… это просто сбой… (FASTMM4 сообщает об утечках памяти).

Попробуйте создать простой сервер VCL datasnap — TCP. И добавьте кнопку и этот источник …

 procedure TForm1.Button1Click(Sender: TObject);
var
//  AObject : TObject;
  aJSONVal : TJSONValue;
begin
//  AObject := TObject.Create;
//  ServerContainer1.DSServer1.BroadcastObject('SomeChannel','SomeCallbackID', AObject);
//  AObject.Free;

  aJSONVal := TJSONObject.Create;
  ServerContainer1.DSServer1.BroadcastMessage('SomeChannel','SomeCallbackID',aJSONVal);
  // aJSONVal.Free; // Mat pointed out that this is done by the broadcast.
end;
  

Это будет работать — до тех пор, пока вы продолжаете использовать TJSONValue …
Но попробуйте переключить прокомментированный код — и вы поймете, что я имею в виду.

Я мог бы, конечно, изменить весь мой существующий код на JSON… но это просто неприемлемо.

Есть ли у кого-нибудь идеи о том, как использовать BroadcastOBJECT или NotifyOBJECT?

С уважением, Бьярне

Комментарии:

1. @Bimmer_R- Предложение: пожалуйста, объясните нам, как происходит сбой — что происходит? Какое исключение вызывает Delphi? Какое сообщение об ошибке вы получаете? Я не думаю, что вы получите много ответов, просто сказав нам «это просто сбой» и попросив нас пойти и создать сервер datasnap и выяснить, что происходит, а что нет.

2. @Mikey … Извините .. конечно, я должен предоставить всю необходимую информацию. Когда я говорю «сбой» — это означает нарушение доступа .. или, как я указал. Fastmm4 сообщает об утечках памяти. Для создания серверного приложения datasnap. на самом деле вам нужно так мало шагов / кликов, что это почти так же быстро, как запуск нового приложения vcl forms 🙂 Вот отличный пример того, как настроить сервер datasnap и использовать обратный вызов. edn.embarcadero.com/article/41374 Единственное отличие, как я вижу, заключается в том, что Im вещает с сервера… но это действительно не должно быть проблемой .. или это так?

Ответ №1:

Объект, который вы передаете вызову Notify или Broadcast, затем принадлежит этому вызову. Поэтому не вызывайте «AObject.Free;» или «aJSONVal.Бесплатно;». Это часто приводит к нарушению доступа или другим проблемам, связанным с управлением памятью.

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

Я надеюсь, что это поможет,

Мат

Комментарии:

1. Привет, мат. Спасибо за ваш интерес к этому. Я модифицировал демонстрационную программу CallbackChannels — и разместил ее на megaupload (не знал, как обмениваться файлами через SO — если это возможно). megaupload.com/?d=BL0SZC98 Помните — выполнение широковещательного обратного вызова для callbackid … все равно не сработает. Но трансляция на канал — это нормально. И notifyobject для callbackid / clientid также в порядке. Я надеюсь, вы найдете демонстрационную версию полезной.

Ответ №2:

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

Справка по Delphi XE: (ms-help://embarcadero.rs_xe/vcl/DSServer.TDSServer.BroadcastObject.html ):

функция BroadcastObject (const ChannelName: строка; const CallbackId: строка; const Msg: TObject): логическое значение; перегрузка;

Вторая перегрузка отправляет объект всем обратным вызовам клиента с заданным зарегистрированным идентификатором обратного вызова. Для этой цели в вызове требуется дополнительный параметр CallbackId.»

Вы используете вторую перегрузку, которая принимает 3 параметра — правильно ли настроены ваши идентификаторы обратного вызова?

Комментарии:

1. Привет, Майки. Вы правы — для каждого из широковещательных методов существует две перегрузки. Но, поскольку я прочитал «инструкции» .. трансляция не нуждается в какой-либо «настройке». Вы можете транслировать что угодно — в любое время, когда захотите. Если никто не слушает, то это не имеет значения. И с 4 возможными трансляциями — я могу заставить работать только одну. Все остальные завершаются неудачей из-за нарушения доступа или утечки памяти.

2. @Bimmer_R: Я бы не назвал ошибки утечки mem как таковые. Но AV-файлы — они генерируются на стороне клиента или сервера? Как настроено ваше развертывание? У вас есть клиенты на удаленных машинах или все локально? Можете ли вы проследить весь путь выполнения до AV? Какую версию Delphi вы используете? Включен ли у вас в IDE параметр ‘break on Delphi language expections’? Как я уверен, вы знаете, AV часто маскирует реальную проблему. Если исключение генерируется на удаленном клиенте, оно может отображаться как AV от серверного вызова, который маскирует фактическое исключение на стороне клиента. Пожалуйста, — подробности! HTH

3. @Bimmer_R — и я так понимаю, что когда вы говорите «это просто сбой», вы имеете в виду, что иногда вообще НИЧЕГО не происходит, за исключением того, что вы видите сообщение об утечке, верно? «Я могу заставить работать только один. Все остальные завершаются сбоем из-за нарушения доступа или утечки памяти » — чем отличается тот, который работает? Это может привести вас к вашему ответу.

4. @Mikey. Еще раз привет — теперь у меня кое-что работает. И я хотел бы поделиться своими знаниями. Выполнение BroadCastObject для канала (всех обратных вызовов / клиентов) довольно просто. И, по-видимому, то же самое относится к NotifyObject (определенному каналу, обратному вызову, клиенту). Где я терплю неудачу, это BroadCastObject для определенного обратного вызова. По какой-то причине это не сработает. Я модифицировал демонстрационную программу embacadero CallBackChannels и отправил ее по почте Павлу Гловацки, с которым я только что посетил двухдневный семинар по этой области. Дайте мне знать, если кто-нибудь захочет получить модифицированную версию ChannelCallbackDemo.

5. @Bimmer_R — Спасибо за согласие — я на самом деле ничего не ответил, но, полагаю, я двигался в правильном направлении? Теперь эта модифицированная версия делает то, что вам нужно? Если это так, я хотел бы это увидеть — сейчас эта функция не используется, но она очень мощная, и хотелось бы знать, как ее правильно использовать при необходимости. Спасибо