Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage the return value of a thread?

I created a class derived from TThread that executes in background a query.

I want that this class is decoupled from the client.

This kind of thread has the purpose of executing a simple check (like how many users are currently connected to the application, without blocking the UI), so a simple idea is to use the Synchronize Method.

Anyway since i want it to be decoupled i pass in the constructor a parameter of type

TSyncMethod: procedure of object;

Where TSyncMethod is a method on the client (a form in my case).

Anyway how can I pass the value to TSyncMethod? I should write the result on some "global place" and then inside my TSyncMethod I check for it?

I also tried to think of

TSyncMethod: procedure(ReturnValue: integer) of object;

but of course when I call Synchronize(MySyncMethod) I cannot pass parameters to it.

like image 313
LaBracca Avatar asked Nov 09 '10 17:11

LaBracca


2 Answers

For such a simply example, you can put the desired value into a member field of the thread (or even into the thread's own ReturnValue property), then Synchronize() execution of the callback using an intermediate thread method, where you can then pass the value to the callback. For example:

type
  TSyncMethod: procedure(ReturnValue: integer) of object;

  TQueryUserConnected = class(TThread)
  private
    FMethod: TSyncMethod;
    FMethodValue: Integer;
    procedure DoSync;
  protected
    procedure Execute; override;
  public
    constructor Create(AMethod: TSyncMethod); reintroduce;
  end;

constructor TQueryUserConnected.Create(AMethod: TSyncMethod);
begin
  FMethod := AMethod;
  inherited Create(False);
end;

procedure TQueryUserConnected.Execute;
begin
  ...
  FMethodValue := ...;
  if FMethod <> nil then
    Synchronize(DoSync);
end;

procedure TQueryUserConnected.DoSync;
begin
  if FMethod <> nil then
    FMethod(FMethodValue);
end;
like image 179
Remy Lebeau Avatar answered Sep 28 '22 10:09

Remy Lebeau


Using OmniThreadLibrary:

uses OtlFutures;

var
  thread: IOmniFuture<integer>;

thread := TOmniFuture<integer>.Create(
  function: integer;
  begin
    Result := YourFunction;
  end;
);
// do something else
threadRes := thread.Value; //will block if thread is not yet done

Creating the TOmniFuture object will automatically start background thread executing your code. Later you can wait on result by calling .Value or you can use .TryValue or .IsDone to check if the thread has already completed its work.

like image 36
gabr Avatar answered Sep 28 '22 12:09

gabr