接收并返回TObject的TDBXCallback的重载执行方法中的错误

时间:2017-01-29 11:26:42

标签: 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): 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;

以下是Matt DeLong提供的视频中的一个例子

Heavyweight Callbacks with DataSnap - Part 1: Thick Client

回调效果很好,但只有一次!在服务器的第二次调用(Button2Click)上,我在客户端获得了一个AV。它可能是DBX代码中的错误。我不知道。我无法在那里追踪。或者我可能错误地从ServerChannelCallBack.Execute初始化了Result。任何帮助表示赞赏。

更新

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

        TFormClient = class(TForm)
          CMServerChannel: TDSClientCallbackChannelManager;
        ...
        private
          ServerChannelCBID: string;
        ...
       procedure TFormClient.FormCreate(Sender: TObject);
       begin
          ServerChannelCBID := DateTimeToStr(now);
          CMServerChannel.RegisterCallback(
            ServerChannelCBID,
            ServerChannelCallback.Create
          );
        ...

1 个答案:

答案 0 :(得分:2)

我的答案基于DataSnap Server + Client项目,可以使用`File |从Delphi Seattle内部下载。从版本控制中打开'

https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE/Delphi/DataSnap/CallbackChannels

这里提到的是: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中显示的代码的变化,服务器和客户端运行正常,我可以根据需要多次单击服务器按钮,服务器和任何客户端都无法获得& #34;卡住&#34 ;.因此,我认为您的问题必须特定于您正在使用的代码中的某些内容,但至少链接的项目会为您提供一些工作方式并与之进行比较。

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