iTask - como usar variáveis como parâmetros para o procedimento TTask
Preciso criar um número de iTasks que preencherão a mesma matriz em posições diferentes. Como o código a ser executado para cada tarefa é o mesmo, decidi criar uma matriz de iTasks e criei 4 tarefas. Eu tive um problema ao passar parâmetros para o procedimento principal dentro do iTask. quando eu uso variáveis como parâmetros, apenas os valores da última tarefa criada estão sendo considerados. Quando passo os parâmetros como valores (codificados), ele respeita todos os valores de cada tarefa. Por favor, veja meu código:
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
UNTThreads, Vcl.StdCtrls,
System.Threading ;
type
Vet = array of integer;
type
TFMThreadArray = class(TForm)
EDTArraySize: TEdit;
EDTNumberofThreads: TEdit;
Memo1: TMemo;
LBArraySize: TLabel;
LBThreads: TLabel;
BTUsingForLoop: TButton;
EDTThread: TEdit;
BTHardCoded: TButton;
procedure BTUsingForLoopClick(Sender: TObject);
procedure BTHardCodedClick(Sender: TObject);
private
{ Private declarations }
procedure ProcA ( Const pin, pfin, Psize, Ptask : integer;
Var Parray : vet);
public
{ Public declarations }
end;
var
FMThreadArray: TFMThreadArray;
implementation
{$R *.dfm}
// Procedure to be called by each iTask
procedure TFMThreadArray.ProcA ( Const pin, pfin, Psize, Ptask : integer;
Var Parray : vet);
var
vind : integer;
begin
for vind := pin to pfin do
begin
Parray[vind] := vind * 10;
end;
end;
==> Este método abaixo, BTHardCodedClick, produz o resultado esperado. Ele preenche a matriz de acordo. MAS é codificado na criação de 4 iTasks e na passagem de parâmetros no ProcA. Eu não quero implementar dessa maneira!
procedure TFMThreadArray.BTHardCodedClick(Sender: TObject);
var
varray : vet;
ind, indtask : Integer;
Ptasks : array of iTask;
begin
memo1.Clear;
SetLength(PTasks,Strtoint(EDTNumberofThreads.text));
SetLength(varray,StrToint(EDTarraysize.text));
// fill array with a initial value -2
for ind := Low(varray) to High(varray) do
varray[ind] :=-2;
// when call ProcA passing values parameters it works propperly
PTasks[0] := TTask.Create( procedure
begin
ProcA(0,3,16,0,varray) ;
end
) ;
PTasks[1] := TTask.Create( procedure
begin
ProcA(4,7,16,1,varray) ;
end
) ;
PTasks[2] := TTask.Create( procedure
begin
ProcA(8,11,16,2,varray) ;
end
) ;
PTasks[3] := TTask.Create( procedure
begin
ProcA(12,15,16,3,varray) ;
end
) ;
for Indtask := Low(Ptasks) to High(Ptasks) do
Ptasks[Indtask].Start;
TTask.WaitForAll(Ptasks);
memo1.Clear;
memo1.Lines.Add(' ============== Creating TASKs with hard-coded parameters ===============');
memo1.lines.add(' Array size : ' + EDTArraySize.text +
' number of Tasks : ' + EDTNumberofThreads.text);
memo1.Lines.Add(' =========================================================');
for ind := Low(varray) to High(varray) do
memo1.Lines.Add(' Array position : ' + Format('%.3d',[ind]) +
' content : ' + varray[ind].ToString );
end;
===> O método a seguir é o que eu quero implementar, mas não está funcionando!, Porque não está preenchendo a matriz. Parece que apenas o último iTask "PTasks [indtask]" está sendo executado.
procedure TFMThreadArray.BTUsingForLoopClick(Sender: TObject);
var
varray : vet;
Ptasks : array of iTask;
vind, indtask, vslice : Integer;
vfirst, vlast, vthreads, vsize : Integer;
begin
vthreads := Strtoint(EDTNumberofThreads.text);
vsize := StrToint(EDTArraysize.text);
SetLength(PTasks,vthreads);
SetLength(varray,vsize);
for vind := Low(varray) to High(varray) do
varray[vind]:=-33;
vslice := Length(varray) div vthreads;
for indtask := Low(PTasks) to High(PTasks) do
begin
vfirst := indtask * vslice;
vlast := (indtask + 1) * vslice - 1;
if (Length(varray) mod vthreads <> 0) and (indtask = High(Ptasks)) then
vlast := HIgh(varray);
PTasks[indtask] := TTask.Create( procedure
begin
procA(vfirst,vlast,vsize,indtask,varray) ;
end
) ;
end;
// Starting all Tasks
for Indtask := Low(Ptasks) to High(Ptasks) do
Ptasks[Indtask].Start;
// Waits until all Tasks been concluded
TTask.WaitForAll(Ptasks);
memo1.Clear;
memo1.Lines.Add(' ============= Using For Loop to create the TASKs =====================');
memo1.lines.add(' Array size : ' + EDTArraySize.text +
' number of Tasks : ' + EDTNumberofThreads.text);
memo1.Lines.Add(' =========================================================');
for vind := Low(varray) to High(varray) do
memo1.Lines.Add(' Array position : ' + Format('%.3d',[vind]) +
' content : ' + varray[vind].ToString );
end;
end.
Não consigo entender por que uma chamada para procA (vfirst, vlast, vsize, indtask, varray) dentro do iTask não está considerando os valores dos parâmetros vfirst, vlast. Agradeço antecipadamente por sua ajuda !