/ / TObjectを受け入れて返すTDBXCallbackのオーバーロードされた実行メソッドのバグ-delphi、callback、datasnap

TObjectを受け入れて返すTDBXCallbackのオーバーロードされたexecuteメソッドのバグ - デルファイ、コールバック、データスナップ

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;

これは、MattDeLongによって提示されたビデオの例に続くものです

DataSnapを使用したヘビーウェイトコールバック-パート1:シッククライアント

コールバックは完全に機能しますが、正確にのみ機能します一度!サーバーからの2回目の呼び出し(Button2Click)で、クライアントにAVを取得します。 DBXコードのバグである可能性があります。わからない。そこをたどることができない。または、ServerChannelCallBack.Executeからの結果を正しく初期化していない可能性があります。どんな援助も大歓迎です。

更新

コールバックは次のようにクライアントに登録されます。

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

回答:

回答№1は2

私は「この回答は、「ファイル|バージョン管理から開く」を使用してDelphiSeattle内からダウンロードできるDataSnapサーバー+クライアントプロジェクトに基づいています。

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では、サーバーとクライアントは正常に動作しており、サーバーボタンを何度でもクリックでき、サーバーもクライアントも「スタック」しません。したがって、問題は使用しているコード内の何かに固有である必要があると思いますが、少なくともリンクされたプロジェクトは、作業して比較するための何かを提供します。

ところで、私は変更しました TCallbackClient.Execute 戻り値の型 TJSONTrue.Create (他のオーバーライドと同じ)それが何であるかMarcoCantuのDelphi2010ハンドブックには、ServerMethodの実行中に「軽量」コールバックのコンテキストで返される必要があると記載されています。TJSONFalseを返すと、実行中のServerMethodをキャンセルするようサーバーに指示されます。ただし、サーバーからのコールバックは機能します。同様によく TObject.Create 使いました。