function S1: TThread; begin Result := TThread.CreateAnonymousThread(procedure() begin TThread.Sleep(9000); Writeln('s1 ...'); end); Result.start; end;
function S2: TThread; begin Result := TThread.CreateAnonymousThread(procedure() begin TThread.Sleep(1000); Writeln('s2 ...'); end); Result.start; end;
function SS: TThread; begin var t1 := S1; while not T1.Finished do ;
var t2 := S2; while not t2.Finished do ;
Result := TThread.CreateAnonymousThread(procedure() begin TThread.Sleep(1000); Writeln('ss ...'); end); Result.Start; end;
begin try var s: string; Writeln('begin...'); var t3 := SS; while not T3.Finished do ; Writeln('end...'); Readln(s); Writeln(s); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
----------------------------------------------
学无止境
S3 = your thread default or a task S3 = { a := S1; b := S2; .... }
that way, S3 will receive the values after S1 and S2 run
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
procedure AsyncAwaitTh(async, await: TProc); begin TThread.CreateAnonymousThread( procedure begin async();
TThread.Queue(nil, procedure begin await(); end ); // TThread.Queue end ).Start; end;
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
In fact, YOU DONT NEED ANY LOCK / UNLOCK in your threads! Just use the "IFUTURE" tasks to call the resulted when you needs it! The procedures will called just when necessary, not before, not later!
type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); ... end;
var Form1: TForm1;
implementation
{$R *.dfm}
uses System.Threading;
var LTaskRUN: ITask;
function MyFunc001ToReturnAnyValue: integer; var LResult: integer; begin sleep(400); // simulating a delay... // LResult := 10; result := LResult; // TThread.Queue(nil, // just for tests... procedure begin Form1.Memo1.Lines.Add(TimeToStr(now, FormatSettings) + ', Func001 = ' + LResult.ToString); end); end;
function MyFunc002ToReturnAnyValue: integer; var LResult: integer; begin sleep(750); // simulating a delay... // LResult := 20; result := LResult; // TThread.Queue(nil, // just for tests... procedure begin Form1.Memo1.Lines.Add(TimeToStr(now, FormatSettings) + ', Func002 = ' + LResult.ToString); end); end;
function MyFunc003ToReturnAnyValue(AValue001, AValue002: integer): integer; var LResult: integer; begin sleep(500); // simulating a delay... // LResult := AValue001 + AValue002; result := LResult; // TThread.Queue(nil, // just for tests... procedure begin Form1.Memo1.Lines.Add(TimeToStr(now, FormatSettings) + ', Func003 = ' + LResult.ToString); end); end;
procedure TForm1.Button1Click(Sender: TObject); var LFutureOne: IFuture<integer>; LFutureTwo: IFuture<integer>; // LText : string; LResulted : integer; LTimeElapsed: UInt64; begin Button1.Enabled := false; // to avoid "double click"... // FormatSettings.LongTimeFormat := 'hh:nn:ss.zzz'; // Memo1.Lines.Clear; // LFutureOne := TTask.Future<integer>(MyFunc001ToReturnAnyValue); // 400ms LFutureTwo := TTask.Future<integer>(MyFunc002ToReturnAnyValue); // 750ms // LTaskRUN := TTask.Run( procedure begin LTimeElapsed := GetTickCount64; // // when "LFutureXXXX.VALUE" is called, then it will be executed (in fact)!!! LResulted := MyFunc003ToReturnAnyValue(LFutureOne.Value, LFutureTwo.Value); // 500 ms // LTimeElapsed := GetTickCount64 - LTimeElapsed; // LFutureOne := nil; LFutureTwo := nil; // // Total time: Func002 + Func003 = 1250ms (+/-) LText := format('S3 = S1 + S2 is: %d, at %d (ms)', [LResulted, LTimeElapsed]); // Form1.Memo1.Lines.Add(TimeToStr(now, FormatSettings) + ', TTask.RUN(...) ' + LText); // Button1.Enabled := true; end); end;
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin if (LTaskRUN = nil) then CanClose := true else CanClose := LTaskRUN.Status in [TTaskStatus.Completed, TTaskStatus.Canceled, TTaskStatus.Exception]; // if CanClose then LTaskRUN := nil; end;
initialization
ReportMemoryLeaksOnShutdown := true;
end.
此帖子包含附件: 大小:247.4K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
procedure TForm1.Button1Click(Sender: TObject); var LFutureOne: IFuture<integer>; LFutureTwo: IFuture<integer>; begin // you can invert the sequence if needs! LFutureOne := TTask.Future<integer>(MyFunc001ToReturnAnyValue); // MyFunc002... LFutureTwo := TTask.Future<integer>(MyFunc002ToReturnAnyValue); // MyFunc001... // TTask.Run( procedure begin MyFunc003ToReturnAnyValue( LFutureOne.Value, LFutureTwo.Value ); end); .......... Func001 = 400ms Func002 = 750ms Func003 = 500ms
Total Time: Func2 + Func3 ( 750 + 500 ) = 1250 (+/-) ms
---------- REMEMBER THIS: ---------- Your tasks is not necessary use "THREADs" because you do the "sequencial tasks"! --> Func3 wait Func2... Func2 wait Func1.
as said above, better is:
Task.RUN( procedure begin Func1; Func2; Func3; end); );
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
a little fix to avoid "close" form whike the tasks is running!
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3