2017-09-28 45 views
4

我創建了一個通用線程類,用於控制在線程的構造函數中注入的進度表,並設置爲_progressForm。在Execute方法,線程初始化形式)顯示了使用功能的ShowModal(它,如下圖所示:爲什麼Synchronize被ShowModal鎖定?

procedure TProgressThread.Execute; 
begin 
    ... 
    ShowForm; 
end; 

procedure TProgressThread.ShowForm; 
begin 
    if Assigned(_progressForm) then 
    begin 
    Synchronize(
     procedure 
     begin 
     _progressForm.ShowModal(); 
     end); 
    end; 
end; 

我不能理解的是,爲什麼我的線程在同步鎖定?在進度表關閉之前它不會返回。不應該ShowModal只鎖定主線程?

+4

如果使用Synchronize,則調用線程將被阻塞直到它返回。 ShowModal在主線程的上下文中運行,所以它將阻塞直到窗體關閉。 –

+0

好像你對一個共同的問題採取了錯誤的方法。適當的解決方案是在線程內執行* *工作*,而不是顯示* progress *。 –

+0

這是一個從主線程調用ShowModal的小bug。想想看。 –

回答

11

TThread.Synchronize()同步。它阻塞調用線程,直到同步代碼從主線程返回。

ShowModal()也是同步。它阻塞調用線程,直到窗體關閉。

所以,當Synchronize()來電ShowModal()在主線程,Synchronize()不會回到工作者線程,直到窗體關閉。

如果你不希望阻止的工作線程,要麼使用TThread.Queue()代替TThread.Synchronize(),或使用TForm.Show(),而不是TForm.ShowModal()

顯示進度不應該阻止工作線程執行其工作。你應該有線程異步後進度更新到主線程,並讓主線程決定如何顯示狀態,而線程繼續其工作。工作者線程根本不應該知道UI。

+0

Remy如何使用PostMessage將進度發佈到主線程 –

+0

@NasreddineAbdelillahGalfout:這非常好,只要您使用對於該用法安全的'HWND'即可。不要使用'TWinControl :: Handle'屬性中的'HWND'!它不是持久的,也不是線程安全的。使用'AllocateHWND()'或'CreateWindow/Ex()'創建自己的'TApplication :: Handle'或'HWND', –

相關問題