首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 長時間迴圈讓出 CPU 控制權:Application.ProcessMessages 避免介面凍結

     編輯:Delphi

問題現象

執行耗時的 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 可能觸發使用者再次點擊同一按鈕,導致遞迴呼叫。需啟用旗標或禁用按鈕防禦。
  • 效能影響:頻繁呼叫會降低迴圈速度;建議每 N 次 (如 100~1000) 呼叫一次。
  • 現代最佳實務:將耗時工作移至背景執行緒 (TThread、TTask.Run、IOmniTask),主執行緒專責 UI,透過 Synchronize/Queue 更新介面,徹底避免凍結與重入問題。

執行緒版本範例 (Delphi 10.4+)

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;
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved