2017-01-29 2 views
0

Там в перегруженной версии Execute функции TDBXCallback вызывает в Data.DBXJSon, который выглядит, как этотОшибки в перегружено выполнить метод TDBXCallback, который принимает и возвращает TObject

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 Делонг

Heavyweight Callbacks with DataSnap - Part 1: Thick Client

Обратный вызов отлично работает, но только один раз! При втором вызове с сервера (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 
     ); 
     ... 
+1

Не взглянув на код dbx, я бы предположил, что функция должна возвращать тот же объект, который был передан ему: Результат: = Arg; а не создавать новую. – dummzeuch

+0

@ dummzeuch Я изменил код, чтобы сделать именно это (Результат: = Arg), но я получил тот же результат. Я думаю, что это ошибка, я должен отчитываться перед Качественным Порталом. – nolaspeaker

+0

Если бы я опубликовал весь код, он бы обфускал вопрос. Ясно, что люди не используют ТАК, как они привыкли, просто из-за таких людей, как вы. – nolaspeaker

ответ

2

Я основывая этот ответ на проекты сервера DataSnap + клиент, который можно загрузить с внутри Delphi Сиэтле, используя `Файл | Открыть из системы управления версиями»

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, сервер и клиент работают нормально, и я могу нажать кнопку сервера столько раз, сколько мне нравится, и ни сервер, ни кто-либо из клиентов ge t "застрял". Поэтому я думаю, что ваша проблема должна быть специфичной для кода в коде, который вы используете, но, по крайней мере, связанный проект дает вам возможность работать и сравнивать.

Btw, я изменил тип TCallbackClient.Execute возврата к TJSONTrue.Create (такой же, как и другие переопределения), потому что это то, что он говорит в Delphi Марко Канту в 2010 Руководство говорит, что должен вернуться, правда, в контексте «легкого» обратного вызова в то время как ServerMethod выполняет: возвращение TJSONFalse сообщает серверу отменить исполняемый серверный метод. Однако обратные вызовы с сервера работают одинаково с используемым вами TObject.Create.

+0

Это был отличный ответ. Имейте в виду, что я работаю над обновлением Delphi 10.1 2. Итак ... Я изменил источник из репозитория, как вы предложили, и такая же ошибка клиента возникает, как и в моем собственном примере кода, при втором нажатии кнопки сервера1. «Project DBXClientChannels.exe поднял класс исключений $ C0000005 с нарушением права доступа на 0x00450987: прочитайте адрес 0x00011cb8 '. – nolaspeaker

+0

В таком случае, если бы я был вами, я бы сообщил об этом Emba как ошибку DataSnap, которая проползала между Сиэтлом и 10.1 обновление 2. Не должно быть трудно воспроизвести. Я отступил от своего VTC. – MartynA

+0

Я действительно благодарен вам за участие в этом endevour. Когда есть ошибка в EMBT, вы бесконечно стучите головой против пресловутой стены. если EMBT знает, сколько времени тратит время на их неосторожность? – nolaspeaker

Смежные вопросы