title: iTask - how to use variables as parameters to TTask procedure
body: <p>I need to create a number of iTasks that will populate the same array in different positions. Since the code to be performed for each Task is the same, I decided to create an array of iTasks and created 4 tasks.  I got a problem when passing parameters to the major procedure inside the iTask. when I use variables as parameters , only the values of the last Task created are being considered.  When I pass the parameters as values (hard-coded) it respect all values for each task.  Please see my code :</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>==> This below method,  BTHardCodedClick, produces the expected result.  It populates the array accordingly. BUT it is hard coded in creating 4 iTasks and in passing parameters in ProcA. I don't want to implement this way !</p>
  
  <pre><code>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;
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/yWvo8.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/yWvo8.jpg" alt="enter image description here"></a></p>
  
  <p>===>  The following method is the one I want to implement BUT it is not working !, because it is not populating the array.  It seems that only the last iTask " PTasks[indtask]" is being performed. </p>
  
  <pre><code>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 &lt;&gt; 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.
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/anw9F.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/anw9F.jpg" alt="enter image description here"></a>
  I can't understand why a call to procA(vfirst,vlast,vsize,indtask,varray) inside the iTask  is not considering the values of parameters vfirst, vlast. 
  Thanks in advance for your help !</p>