2017-09-28 49 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', –

相关问题