單一執行緒執行耗時迴圈時,訊息佇列無法處理,視窗會「假死」(無法拖曳、重繪、回應關閉)。
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 500000 do
begin
Canvas.TextOut(10, 10, IntToStr(i));
Application.ProcessMessages; { 處理訊息佇列 }
end;
end;
缺點:拖曳視窗時迴圈暫停,非真正並行,CPU 仍被單一執行緒佔用。
function MyFun: Integer;
var
i: Integer;
begin
for i := 0 to 500000 do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(10, 10, IntToStr(i));
Form1.Canvas.Unlock;
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
MyFun; { 仍在主執行緒執行 }
end;
關鍵習慣:Canvas.Lock/Unlock 保護 GDI 資源,未來擴充為多線程時無需重構。
function MyFun(p: Pointer): Integer; stdcall;
var
i: Integer;
begin
for i := 0 to 500000 do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(10, 10, IntToStr(i));
Form1.Canvas.Unlock;
end;
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ID: DWORD;
begin
CreateThread(nil, 0, @MyFun, nil, 0, ID);
end;
重點:
stdcall 嚴格符合 Win32 規範。type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TMyThread.Execute;
var
i: Integer;
begin
FreeOnTerminate := True; { 關鍵:執行緒結束自動 Free 實例 }
for i := 0 to 500000 do
begin
Form1.Canvas.Lock;
Form1.Canvas.TextOut(10, 10, IntToStr(i));
Form1.Canvas.Unlock;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyThread.Create(False); { False = 立即執行 }
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyThread: TMyThread;
begin
MyThread := TMyThread.Create(True); { True = 建立後暫停 }
MyThread.Resume; { 手動啟動 }
{ 簡寫:with TMyThread.Create(True) do Resume; }
end;
操作步驟(對應動畫):
thread 選擇範本。
True。False。FreeOnTerminate := True,否則需手動追蹤實例並 Free,極易洩漏。從 ProcessMessages 到 CreateThread 再到 TThread,三種方式層層遞進。掌握 Lock/Unlock、stdcall、FreeOnTerminate 三大關鍵點,即可安全邁入 Delphi 多線程開發大門。後續將深入 CreateThread 參數細節與同步機制。