在 IdTCPServer.OnConnect 事件(執行於工作線程)中直接調用 Form.Show 會導致死鎖,原因是 VCL 不支援多線程直接操作 UI,且窗體創建/顯示涉及消息泵與鎖競爭。
procedure TServerForm.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
Form2.Show; {死鎖!Form2 含 Button/ListBox 等控件時必現}
end;
procedure TServerForm.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
Timer1.Enabled := True; {Interval=1}
end;
procedure TServerForm.Timer1Timer(Sender: TObject);
begin
Form2.Show;
Timer1.Enabled := False;
end;
利用 Timer 事件回到主線程執行,但屬於「大腦短路」式修補。
procedure TServerForm.IdTCPServer1Connect(AThread: TIdPeerThread);
begin
AThread.Synchronize(Form2.Show); {正確:在主線程執行匿名方法}
end;
TIdPeerThread.Synchronize 將方法排隊到主線程執行,是 Indy 線程安全操作 UI 的標準方式。
Synchronize 或 TThread.Queue