Има претоварена версия на функцията Execute на TDBXCallback обаждания в Data.DBXJSon, която изглежда така
function Execute(Arg: TObject): TObject; overload; virtual; abstract;
Което в моя клиент на Datasnap реализирах така:
type
ServerChannelCallBack = class(TDBXCallback)
public
function Execute(const Arg: TJSONValue): TJSONValue; overload; override; // this works!
function Execute(Arg: TObject): TObject; overload; override; // this doesn"t
end;
function ServerChannelCallBack.Execute(Arg: TObject): TObject;
var
i: Integer;
begin
Result := TObject.Create; // is this correct?
try
if Arg is TStringList then
begin
FormClient.QueueLogMsg("ServerChannel", "Got TStringList");
for i := 0 to TStrings(Arg).Count - 1 do
FormClient.QueueLogMsg("ServerChannel", TStringList(Arg)[i]);
end;
finally
end;
end;
Това се извиква от сървъра на Datasnap така:
procedure TFormServer.Button2Click(Sender: TObject);
var
sr: TStringList;
begin
sr := TStringList.Create;
try
sr.Add("one");
sr.Add("two");
ServerContainer2.DSServer1.BroadcastObject("SERVERCHANNEL", sr);
finally
// sr
end;
end;
Това следва от пример във видеото, представено от Мат ДеЛонг
Обратни повиквания в тежко тегло с DataSnap - Част 1: Дебел клиент
Обратното извикване работи перфектно, но само точноведнъж! При второто обаждане от сървъра (Button2Click) получавам AV в клиента. Възможно е грешка в DBX кода. Не знам. Не мога да проследя там. Или може би съм инициализирал резултата от ServerChannelCallBack.Execute неправилно. Всяка помощ се оценява.
UPDATE
Обратното обаждане се регистрира на клиента така:
TFormClient = class(TForm)
CMServerChannel: TDSClientCallbackChannelManager;
...
private
ServerChannelCBID: string;
...
procedure TFormClient.FormCreate(Sender: TObject);
begin
ServerChannelCBID := DateTimeToStr(now);
CMServerChannel.RegisterCallback(
ServerChannelCBID,
ServerChannelCallback.Create
);
...
Отговори:
2 за отговор № 1Основавам този отговор на проектите на DataSnap Server + Client, които могат да бъдат изтеглени от Delphi Seattle с помощта на „File | Open от контрола на версиите“
това е споменато тук: http://edn.embarcadero.com/article/41374.
Формите както в сървъра, така и в клиента изискват лека корекция, за да ги накарат да компилират, име да добавят JSon
към списъка им за употреба
В сървърната форма добавих следното:
procedure TForm3.Button1Click(Sender: TObject);
var
sr: TStringList;
begin
Inc(CallbackCount); // A form variable
sr := TStringList.Create;
try
sr.Add("Callback: " + IntToStr(CallbackCount));
sr.Add("two");
ServerContainer1.DSServer1.BroadcastObject("ChannelOne", sr);
finally
// No need for sr.free
end;
end;
(Използвам ChannelOne за съгласуваност с клиента)
и на клиента имам:
function TCallbackClient.Execute(Arg: TObject): TObject;
var
i: Integer;
begin
// Result := TObject.Create; // is this correct?
Result := TJSONTrue.Create;
try
if Arg is TStringList then
begin
QueueLogValue("Server: Got TStringList");
for i := 0 to TStrings(Arg).Count - 1 do
QueueLogValue("Server:" + TStringList(Arg)[i]);
end;
finally
end;
end;
С тези вариации от кода, който показахтевъв вашия q сървърът и клиентът работят добре и мога да щракна върху бутона на сървъра толкова пъти, колкото ми харесва и нито сървърът, нито някой от клиентите не се „забиват“. Затова смятам, че проблемът ви трябва да е специфичен за нещо в кода, който използвате, но поне свързаният проект ви дава нещо, от което можете да работите и да сравните.
Btw, промених TCallbackClient.Execute
вид на връщане към TJSONTrue.Create
(същото като другото отмяна), защото това е каквов „Наръчника за Delphi 2010“ на Марко Канту пише, че трябва да се върне, разбира се, в контекста на „лек“ обратен разговор, докато ServerMethod се изпълнява: връщането на TJSONFalse казва на сървъра да отмени изпълняващия ServerMethod. еднакво добре с TObject.Create
ти използва.