Delphi TDBXCallback的重载执行方法中存在接受并返回ToObject的错误
Data.DBXJSon中的TDBXCallback调用的Execute函数有一个重载版本,如下所示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):
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中相同的客户端错误