執行耗時的 for、while 迴圈時,主執行緒被佔用,訊息佇列無法處理,導致視窗無法重繪、無法移動、點擊無反應(「假死」)。
在迴圈內定期呼叫 Application.ProcessMessages,讓訊息迴圈處理暫存的繪圖、輸入、計時器等訊息。
procedure TForm1.LongTaskButtonClick(Sender: TObject);
var
i: Integer;
begin
for i := 1 to 1000000 do
begin
// 執行耗時運算
HeavyCalculation(i);
// 每 1000 次迴圈讓出一次控制權
if (i mod 1000) = 0 then
Application.ProcessMessages;
// 可選:檢查使用者是否取消
if FCancelled then Break;
end;
end;
ProcessMessages 可能觸發使用者再次點擊同一按鈕,導致遞迴呼叫。需啟用旗標或禁用按鈕防禦。TThread、TTask.Run、IOmniTask),主執行緒專責 UI,透過 Synchronize/Queue 更新介面,徹底避免凍結與重入問題。uses System.Threading;
procedure TForm1.ModernLongTaskClick(Sender: TObject);
begin
TTask.Run(
procedure
var
i: Integer;
begin
for i := 1 to 1000000 do
begin
HeavyCalculation(i);
if (i mod 1000) = 0 then
TThread.Queue(nil,
procedure
begin
ProgressBar1.Position := i div 1000;
end);
end;
end);
end;