Delphi TDBXCallback的重载执行方法中存在接受并返回ToObject的错误

Delphi TDBXCallback的重载执行方法中存在接受并返回ToObject的错误,delphi,callback,datasnap,Delphi,Callback,Datasnap,Data.DBXJSon中的TDBXCallback调用的Execute函数有一个重载版本,如下所示 function Execute(Arg: TObject): TObject; overload; virtual; abstract; 在我的Datasnap客户端中,我实现了如下: type ServerChannelCallBack = class(TDBXCallback) public function Execute(const Arg: TJSONValue):

Data.DBXJSon中的TDBXCallback调用的Execute函数有一个重载版本,如下所示

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;
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;
        TFormClient = class(TForm)
          CMServerChannel: TDSClientCallbackChannelManager;
        ...
        private
          ServerChannelCBID: string;
        ...
       procedure TFormClient.FormCreate(Sender: TObject);
       begin
          ServerChannelCBID := DateTimeToStr(now);
          CMServerChannel.RegisterCallback(
            ServerChannelCBID,
            ServerChannelCallback.Create
          );
        ...
这是从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;
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;
        TFormClient = class(TForm)
          CMServerChannel: TDSClientCallbackChannelManager;
        ...
        private
          ServerChannelCBID: string;
        ...
       procedure TFormClient.FormCreate(Sender: TObject);
       begin
          ServerChannelCBID := DateTimeToStr(now);
          CMServerChannel.RegisterCallback(
            ServerChannelCBID,
            ServerChannelCallback.Create
          );
        ...
下面是Matt DeLong视频中的一个示例

回调可以很好地工作,但只能执行一次!在服务器的第二次呼叫(Button2Click)中,我在客户端得到一个AV。这可能是DBX代码中的错误。我不知道。我在里面找不到。或者我已经初始化了ServerChannelCallBack的结果。执行不正确。感谢您的帮助

更新

在客户端上注册回调,如下所示:

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;
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;
        TFormClient = class(TForm)
          CMServerChannel: TDSClientCallbackChannelManager;
        ...
        private
          ServerChannelCBID: string;
        ...
       procedure TFormClient.FormCreate(Sender: TObject);
       begin
          ServerChannelCBID := DateTimeToStr(now);
          CMServerChannel.RegisterCallback(
            ServerChannelCBID,
            ServerChannelCallback.Create
          );
        ...

我的回答基于DataSnap服务器+客户端项目,这些项目可以使用“文件|从版本控制打开”从Delphi Seattle内部下载

这里提到的是:

服务器和客户机中的表单都需要稍加修改才能编译,name可以将
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中显示的代码不同,服务器和客户端运行良好,我可以随意多次单击服务器按钮,服务器和任何客户端都不会“卡住”。因此,我认为您的问题一定与您正在使用的代码中的某些内容有关,但至少链接的项目为您提供了一些可供参考和比较的内容


顺便说一句,我将
TCallbackClient.Execute
返回类型更改为
TJSONTrue.Create
(与另一个覆盖相同),因为Marco Cantu的Delphi 2010手册中说它应该返回,这是在“轻量级”的环境中说的ServerMethod执行时回调:返回TJSONFalse告诉服务器取消正在执行的ServerMethod。但是,来自服务器的回调与您使用的
TObject.Create
同样有效。

我的回答基于DataSnap服务器+客户端项目,可以使用“文件”从Delphi Seattle内部下载该项目

这里提到的是:

服务器和客户机中的表单都需要稍加修改才能编译,name可以将
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中显示的代码不同,服务器和客户端运行良好,我可以随意多次单击服务器按钮,服务器和任何客户端都不会“卡住”。因此,我认为您的问题一定与您正在使用的代码中的某些内容有关,但至少链接的项目为您提供了一些可供参考和比较的内容


顺便说一句,我将
TCallbackClient.Execute
返回类型更改为
TJSONTrue.Create
(与另一个覆盖相同),因为Marco Cantu的Delphi 2010手册中说它应该返回,这是在“轻量级”的环境中说的ServerMethod执行时回调:返回TJSONFalse告诉服务器取消正在执行的ServerMethod。但是,来自服务器的回调同样适用于您使用的
TObject.Create

在没有查看dbx代码的情况下,我假设函数应该返回传递给它的相同对象:Result:=Arg;而不是创建一个新的。@dummzeuch我修改了代码以完全实现这一点(Result:=Arg),但得到了相同的结果。我认为这是一个错误,我必须向质量门户网站报告。如果我发布了整个代码,它会混淆问题。很明显,人们不再像以前那样用那么多了,仅仅是因为像你这样的人。我很感激你在这方面花了很多时间,但后来你带着这种我不理解的古怪态度回来了。也许如果我把问题的标题改成更合适的,你会更愿意接受吗?你有什么建议?网上的误会很容易发生,所以不用担心。我把你的标题理解为你通常对如何从DS服务器返回一个对象感兴趣,但现在我知道了。我并不打算采取“wierd态度”,即使在看了链接的视频之后,我也不知道您是如何注册回调的,您的更新现在显示了回调。在没有查看dbx代码的情况下,我假设函数应该返回传递给它的同一个对象:Result:=Arg;而不是创建一个新的。@dummzeuch我修改了代码以完全实现这一点(Result:=Arg),但得到了相同的结果。我认为这是一个错误,我必须向质量门户网站报告。如果我发布了整个代码,它会混淆问题。很明显,人们不再像以前那样用那么多了,仅仅是因为像你这样的人。我很感激你在这方面花了很多时间,但后来你带着这种我不理解的古怪态度回来了。也许如果我把问题的标题改成更合适的,你会更愿意接受吗?你有什么建议?网上的误会很容易发生,所以不用担心。我把你的标题理解为你通常对如何从DS服务器返回一个对象感兴趣,但现在我知道了。我并不是有意要采取“威德态度”,即使在看了链接视频后,我也不知道你是如何注册回拨的,你的更新现在显示了这一点。这是一个很好的答案。请注意,我正在使用Delphi10.1更新2。所以我按照您的建议修改了存储库中的源代码,出现了与m中相同的客户端错误