Reputation: 385
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
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
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
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