Create a VCL Forms Application, put a TButton and a TMemo on the Form, and write this code in the button's OnClick handler:
uses
OtlParallel, OtlTaskControl;
procedure TForm2.btnStartLoopClick(Sender: TObject);
var
starttime: Cardinal;
k: Integer;
begin
mmoTest.Lines.Clear;
for k := 1 to 50 do
mmoTest.Lines.Add('Line ' + IntToStr(k));
starttime := GetTickCount;
Parallel.Async(
procedure
var
i: Integer;
begin
for i := 1 to 50 do
begin
Sleep(100);
mmoTest.Lines[i - 1] := mmoTest.Lines[i - 1] + FormatDateTime(' nn:ss:zzz', Now);
end;
end,
Parallel.TaskConfig.SetPriority(TOTLThreadPriority.tpHighest).OnTerminated(
procedure
begin
mmoTest.Lines.Add(IntToStr(GetTickCount - starttime) + ' milliseconds');
end));
end;
Now run the program and make this test:
Click on the button, simply wait for the loop to complete and look at the time displayed in the last line of the memo: It should be approximately 5300 milliseconds.
Now click again on the button, click and hold the form's title bar and move the form around quickly until the loop has finished. Now look again at the memo's last line: In my tests, the time was over 7000 milliseconds. Obviously, the main thread is blocking the parallel thread!
So how can the main thread blocking the parallel thread be avoided?
First, this code is not thread-safe, as the asynchronous code is directly accessing the
TMemo
from a task thread outside of the main UI thread. You cannot do that. A worker thread MUST synchronize with the UI thread in order to access UI controls safely or else bad things can happen. You can useTThread.Synchronize()
,TThread.Queue()
, orIOmniTask.Invoke()
for that synchronization.Second, while you are holding down the mouse on the title bar, the main UI message loop is blocked (a separate modal message loop is being run by the OS until you let go of the mouse). As such, the task's
OnTerminate
event handler may not be run until the main message loop regains control. That would account for why your timer duration is reportedly longer than expected, not because the task loop was blocked.Third,
Sleep()
is not absolute. It will sleep for at least the requested amount of time, but may sleep for longer. So your task loop will run for at least 5 seconds, but may be a little longer.