try my sample  UI main totally responsive!     unit uFormMain; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class(TForm) btn_Start_TaskRUN: TButton; Edit1: TEdit; Edit2: TEdit; btn_Stop_TaskRUN: TButton; Memo1: TMemo; procedure btn_Start_TaskRUNClick(Sender: TObject); procedure btn_Stop_TaskRUNClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses System.Threading; // Proc: TProc var lMyProc1: TProc = nil; lMyProc2: TProc = nil; lMyProc3: TProc = nil; // lMyValue1: integer = 0; lMyValue2: integer = 0; lMyValue3: integer = 0; // lMyTaskRUN_obj: ITask = nil; // lMyTasks: array [0 .. 2] of ITask = ( nil, nil, nil ); // if is only 3, then... procedure prcTask1; begin // some code pertinent... Sleep(3000); lMyValue1 := 111; end; procedure prcTask2; begin // some code pertinent... Sleep(2000); lMyValue2 := 222; end; procedure prcTask3; begin // some code pertinent... Sleep(5000); lMyValue3 := 333; end; procedure TForm1.btn_Start_TaskRUNClick(Sender: TObject); begin lMyProc1 := prcTask1; lMyProc2 := prcTask2; lMyProc3 := prcTask3; // lMyTaskRUN_obj := TTask.Run( { } procedure() { } begin // lMyTasks[0] := TTask.Create(lMyProc1); lMyTasks[1] := TTask.Create(lMyProc2); lMyTasks[2] := TTask.Create(lMyProc3); // lMyTasks[0].Start; lMyTasks[1].Start; lMyTasks[2].Start; // Edit1.Text := 'Tasks started in: ' + TimeToStr(now); // TTask.WaitForAll(lMyTasks); { boolean return } // wait all task end = 3sec, 2sec and 5sec = 5sec is your time to wait! // TTask.WaitForAny(lMyTasks); { integer return = task ID } // who's end firstly, then, go back! in this case, 2sec < 3sec < 5sec // Edit2.Text := 'Tasks ended in: ' + TimeToStr(now); // (* try TThread.Synchronize(nil, procedure() { } begin { } TTask.WaitForAll(lMyTasks) { } end { } ); finally end; *) // ShowMessage('All done' + { } sLineBreak + lMyValue1.ToString + { } sLineBreak + lMyValue2.ToString + { } sLineBreak + lMyValue3.ToString { } ); end { } ); // TTask.Run... procedure... // end; procedure TForm1.btn_Stop_TaskRUNClick(Sender: TObject); var i : integer; lMyTaskWainting: ITask; begin try if not(lMyTaskRUN_obj = nil) then begin Caption := 'not(lMyTaskRUN_obj = nil)'; // // TTaskStatus = (Created, WaitingToRun, Running, Completed, WaitingForChildren, Canceled, Exception); if (lMyTaskRUN_obj.Status = TTaskStatus.Running) then begin for lMyTaskWainting in lMyTasks do if (lMyTaskWainting.Status in [TTaskStatus.Running, TTaskStatus.WaitingToRun]) then lMyTaskWainting.Cancel; // lMyTaskRUN_obj.Cancel; end; // Self.Close; // close app end else Caption := 'lMyTaskRUN_obj = nil'; except on E: Exception do ShowMessage(E.Message); end; end; initialization ReportMemoryLeaksOnShutdown := true; finalization end.   hug