title: How to stop a running TTask thread-safe?
body: <p>In Delphi 10.1 Berlin I would like to add the possibility to stop the responsive TParallel.&amp;For loop from my question <a href="https://stackoverflow.com/questions/44071313/how-to-make-a-tparallel-for-loop-responsive-and-store-values-in-a-tlistt">How to make a TParallel.&amp;For loop responsive and store values in a TList&lt;T&gt;?</a> . </p>
  
  <p>The loop calculates values and stores these values in a TList. It runs in a separate thread with TTask.Run to make it responsive:</p>
  
  <pre><code>type
    TCalculationProject=class(TObject)
    private
      Task: ITask;
      ...
    public
      List: TList&lt;Real&gt;;
      ...
    end;
  
  procedure TCalculationProject.CancelButtonClicked;
  begin
    if Assigned(Task) then
    begin
      Task.Cancel;
    end;
  end;
  
  function TCalculationProject.CalculateListItem(const AIndex: Integer): Real;
  begin
    //a function which takes a lot of calculation time
    //however in this example we simulate the calculation time and
    //use a simple alogorithm to verify the list afterwards
    Sleep(30);
    Result:=10*AIndex;
  end;
  
  procedure TCalculationProject.CalculateList;
  begin
    List.Clear;
  
    if Assigned(Task) then
    begin
      Task.Cancel;
    end;
  
    Task:=TTask.Run(
      procedure
      var
        LoopResult: TParallel.TLoopResult;
        Lock: TCriticalSection;
      begin
        Lock:=TCriticalSection.Create;
        try
          LoopResult:=TParallel.&amp;For(0, 1000-1,
            procedure(AIndex: Integer; LoopState: TParallel.TLoopState)
            var
              Res: Real;
            begin
  
              if (Task.Status=TTaskStatus.Canceled) and not(LoopState.Stopped) then
              begin
                LoopState.Stop;
              end;
              if LoopState.Stopped then
              begin
                Exit;
              end;
  
              Res:=CalculateListItem(AIndex);
              Lock.Enter;
              try
                List.Add(Res);
              finally
                Lock.Leave;
              end;
            end
          );
        finally
          Lock.Free;
        end;
  
        if (Task.Status=TTaskStatus.Canceled) then
        begin
          TThread.Synchronize(TThread.Current,
            procedure
            begin
              List.Clear;
            end
          );
        end
        else
        begin
          if LoopResult.Completed then
          begin
            TThread.Synchronize(TThread.Current,
              procedure
              begin
                SortList;
                ShowList;
              end
            );
          end;
        end;
      end
    );
  end;
  </code></pre>
  
  <p>The current running calculation Task should be stopped when</p>
  
  <ol>
  <li>the calculation is restarted </li>
  <li>the user click on a cancel button </li>
  </ol>
  
  <p>I added </p>
  
  <pre><code>if Assigned(Task) then
  begin
    Task.Cancel;
  end;
  </code></pre>
  
  <p>at the beginning of <code>procedure TCalculationProject.CalculateList</code> and in <code>procedure TCalculationProject.CancelButtonClicked</code> which is called when the cancel button is clicked.</p>
  
  <p>The loop is stopped with</p>
  
  <pre><code>if (Task.Status=TTaskStatus.Canceled) and not(LoopState.Stopped) then
  begin
    LoopState.Stop;
  end;
  if LoopState.Stopped then
  begin
    Exit;
  end;
  </code></pre>
  
  <p>and the list is cleared with</p>
  
  <pre><code>if (Task.Status=TTaskStatus.Canceled) then
  begin
    TThread.Synchronize(TThread.Current,
      procedure
      begin
        List.Clear;
      end
    );
  end
  </code></pre>
  
  <p>This does not work when I restart the calculation. Then two calculation tasks are running. I tried to add a <code>Task.Wait</code> after <code>Task.Cancel</code> to wait for the task to be finished before we start the new calculation but without success. </p>
  
  <p>What is the correct fully thread-safe way to implement such a cancel/stop function?</p>