Use of Callback in Delphi

Asked

Viewed 2,265 times

2

I’m reformulating my question regarding the Callback methodology.

I would like some specific example or material of how to use Callbacks calls from the server to the client.

Example:

CLIENT SIDE

In the client I have this class Tcallback

TCallback = class(TDBXCallBack)
  Function Execute(const Args: TJSONValue): TJSONValue; override;
  function GetConnectionName(OptionList: OleVariant): String;
  procedure ShowWaitScreen(const Msg: String);
  procedure ReleaseProcessScreen;
  function ShowProcessScreen(const ALinha: String; const ACaption: String;
                          APosition: Integer; ACount2: Integer;):  WordBool;
end;

with the code below somewhere in the client I send Callback to the server

Var
  FCallBack: TCallBack;
  ClientPx: TSMPrincipalClient;  
begin
  if (FCallBack = nil) then begin
     FCallBack := TCallBack.Create();
  end;
  try
    ClientPx := TSMPrincipalClient.Create(conDataSnap.DBXConnection, False);
    ClientPx.SetCallBack(FCallback);
  except
   on E:Exception do
    ExceptionMessage := e.Message;
  end;
end;

SERVER SIDE

From now that this my doubt,the server received the Callback by the method setCallback

procedure TSMPrincipal.SetCallBack(CallBack: TDBXCallback);
var
  FCallBack: TDBXCallback;
begin
  FCallBack := CallBack;
  FConnection.ConnectionName := GetConnectionName;
  FConnection.Connected := True;
end;

There at some point the server call the method in the client, how to do this?

Result := FCallBack.GetConnectionName(Dataset.Data);

1 answer

3

I found a tutorial well completed in the blog of Andreano Lanusse.

When we have a client-server call involving some kind of processing we use Callback so that the server sends the processing status to the client. That said, you must follow the following steps:

1-Implement the server method. This server method receives a Tdbxcallback as parameter.

In the blog Andreano made a server method that performs the backup of a database, returning to the client the last row of the table that was processed:

procedure TDSServerBatch.StartBackup(sMessage: TDBXCallback;
  sBackupFileName: String);
var
  LCallbackValue: TJSONObject;
  db: String;

begin

  db := DMServerContainer.GetEmployeeDBName;

  srvBackup.DatabaseName := Copy(db, Pos(':', db) + 1, Length(db));

  srvBackup.Attach;
  srvBackup.BackupFile.Add(sBackupFileName);

  srvBackup.ServiceStart;
  if srvBackup.Verbose then
    while not srvBackup.Eof do
    begin

      // if srvBackup.IsServiceRunning then
      begin
        LCallbackValue := TJSONObject.Create;
        LCallbackValue.AddPair(TJSONPair.Create('Server return',
            srvBackup.GetNextLine));

        sMessage.Execute(LCallbackValue);

      end;

    end;

  if srvBackup.Active then
    srvBackup.Detach();

end;

2- Implement the client-side.

I find it interesting to use anonymous methods for callback. Why? I explain: When using anonymous methods the callback reference to be executed will be passed from the server to the client, whenever one of its server method is executed. Follow the example below:

type
  TDSCallbackMethod = reference to function(const Args: TJSONValue): TJSONValue;

  TMessageCallback = class(TDBXCallback)
  private
    FCallBackMethod: TDSCallbackMethod;

  public
    constructor Create(CallBackMethod: TDSCallbackMethod);
    function Execute(const Arg: TJSONValue): TJSONValue; override;
  end;

implementation

constructor TMessageCallback.Create(CallBackMethod: TDSCallbackMethod);
begin
  FCallBackMethod := CallBackMethod;
end;

function TMessageCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
  Result := FCallbackMethod(Arg);
end;

3- To run the server method you just need to do this:

//Declarar seu callback (Usei Métodos Anônimos)
callback := TMessageCallback.Create( function(const Args: TJSONValue) : TJSONValue;
//No caso, s é do tipo TDSServerBatchClient, que seria seu proxy em questão.
s := TDSServerBatchClient.Create(DMClientContainer.MyDSServer.DBXConnection);
s.StartBackup(callback, 'mybackup.ibk');

P.S.: Just to conclude, this response was based on material taken from the blog. I wrote it just to have a reference here on the site that does not depend on the link. I suggest you read the post in full for better conclusions.

  • Thanks, @Edgarmunizberlinck !!! Andreano’s material is always very good. I’ll take a look at the full

Browser other questions tagged

You are not signed in. Login or sign up in order to post.