user1937012
user1937012

Reputation: 385

Delphi PPL TTask Procedure with Parameters

I do not know how to Create a TTask where I have a Procedure with parameters, without parameters it works but with parameters it does not .

Example

procedure TMain.SYNC(AProgressBar: TProgressBar; ASleep: Integer);
var i : integer;
begin
  for i := 0 to 100 do
    begin
      sleep(ASleep);

      TThread.Queue(TThread.CurrentThread,
      procedure
      begin
        AProgressBar.Position:=i;
      end);

    end;
end;

Then I would like to create 4 Tasks like this :

setlength(Tasks,4);

  Tasks[0] := TTask.Create(SYNC(progressThread1,100));
  Tasks[1] := TTask.Create(SYNC(progressThread2,150));
  Tasks[2] := TTask.Create(SYNC(progressThread3,300));
  Tasks[3] := TTask.Create(SYNC(progressThread4,200));

  Tasks[0].Start;
  Tasks[1].Start;
  Tasks[2].Start;
  Tasks[3].Start;

Upvotes: 0

Views: 3056

Answers (3)

LU RD
LU RD

Reputation: 34939

Extending Remy's answer.

The loop 0..100 calling TThread.Queue with index i suffers from updating the progressbar with the i reference value, rather than the passed value.

To better view the consequence of this, remove the sleep call and add the i value to a memo. This will reveal a sequence similar to this:

42
101
101
101
...
101

Here is an example of how to capture the value of i when calling TThread.Queue:

procedure TMain.SYNC(AProgressBar: TProgressBar; ASleep: Integer);
  function CaptureValue( ix : Integer) : TThreadProcedure;
  begin
    Result :=
      procedure
      begin
        AProgressBar.Position := ix;
      end;
  end;
var i : integer;
begin
  for i := 0 to 100 do
    begin
      sleep(ASleep);
      TThread.Queue(TThread.CurrentThread, CaptureValue(i) );
    end;
end;

Upvotes: 1

gabr
gabr

Reputation: 26850

Extending the Remy's answer, you can also write a function which returns an anonymous function that you pass to the task.

function MakeSync(AProgressBar: TProgressBar; ASleep: integer): TProc;
begin
  Result :=
    procedure
    begin
      SYNC(AProgressBar, ASleep);
    end;
end;

SetLength(Tasks, 4);

Tasks[0] := TTask.Create(MakeSYNC(progressThread1, 100));
Tasks[1] := TTask.Create(MakeSYNC(progressThread2, 150));
Tasks[2] := TTask.Create(MakeSYNC(progressThread3, 300));
Tasks[3] := TTask.Create(MakeSYNC(progressThread4, 200));

Tasks[0].Start;
Tasks[1].Start;
Tasks[2].Start;
Tasks[3].Start;

Upvotes: 3

Remy Lebeau
Remy Lebeau

Reputation: 598269

TTask operates with anonymous procedures. You can capture the values that you want to pass to your method, eg:

SetLength(Tasks, 4);

Tasks[0] := TTask.Create(
  procedure
  begin
    SYNC(progressThread1, 100);
  end
);
Tasks[1] := TTask.Create(
  procedure
  begin
    SYNC(progressThread2, 150);
  end
);
Tasks[2] := TTask.Create(
  procedure
  begin
    SYNC(progressThread3, 300);
  end
);
Tasks[3] := TTask.Create(
  procedure
  begin
    SYNC(progressThread4, 200);
  end
);

Tasks[0].Start;
Tasks[1].Start;
Tasks[2].Start;
Tasks[3].Start;

Upvotes: 3

Related Questions