2017-01-27 50 views
0

TThread在线程创建时将一个称为ThreadProc的线程函数传递给CreateThread。 这是TThread使用的ThreadProc应终止同步?

function ThreadProc(Thread: TThread): Integer; 
var 
    FreeThread: Boolean; 
begin 
    TThread.FCurrentThread := Thread; 
{$IF Defined(MACOS)} 
    if Thread.FSuspended then 
    pthread_mutex_lock(Thread.FCreateSuspendedMutex); 
{$ELSEIF Defined(LINUX)} 
    if Thread.FSuspended then 
    sem_wait(Thread.FCreateSuspendedSem); 
{$ENDIF LINUX} 
    try 
    if not Thread.Terminated then 
    try 
     Thread.Execute; 
    except 
     Thread.FFatalException := AcquireExceptionObject; 
    end; 
    finally 
    Result := Thread.FReturnValue; 
    FreeThread := Thread.FFreeOnTerminate; 
    Thread.DoTerminate; 
    Thread.FFinished := True; 
    SignalSyncEvent; 
    if FreeThread then Thread.Free; 
{$IF Defined(MSWINDOWS)} 
    EndThread(Result); 
{$ELSEIF Defined(POSIX)} 
    // Directly call pthread_exit since EndThread will detach the thread causing 
    // the pthread_join in TThread.WaitFor to fail. Also, make sure the EndThreadProc 
    // is called just like EndThread would do. EndThreadProc should not return 
    // and call pthread_exit itself. 
    if Assigned(EndThreadProc) then 
     EndThreadProc(Result); 
    pthread_exit(Result); 
{$ENDIF POSIX} 
    end; 
end; 

...这是Thread.DoTerminate代码:

procedure TThread.CallOnTerminate; 
begin 
    if Assigned(FOnTerminate) then FOnTerminate(Self); 
end; 

procedure TThread.DoTerminate; 
begin 
    if Assigned(FOnTerminate) then Synchronize(CallOnTerminate); 
end; 

所以我的问题是;应该OnTerminate是否同步?为什么同步是默认行为?不应该由开发人员决定吗?

我在问,因为我无法弄清楚它为什么会被同步以及这种行为在大多数情况下是否是最好的。

回答

5

TThread类安排在主线程上执行OnTerminate事件处理程序作为方便。它最常用于允许主线程响应线程完成。在这种情况下,代码在主线程上执行是非常有用的。例如,通常清除对线程的引用,或者在线程终止时执行UI任务。通过在主线程上执行事件处理程序,这些任务将自动在正确的线程上执行。

如果您希望此时在线程中执行工作,则可以覆盖DoTerminate并将工作放在那里。

换句话说,你仍然有选择。如果您想让代码在主线程上运行,请将其放入OnTerminate事件处理程序中。如果您希望代码在线程中运行,请覆盖DoTerminate

+0

我注意到它可以重写,我不介意这样做,但我想我不明白为什么同步会是首选的默认行为。我知道这可能听起来像挑剔我的一部分,但对我来说这似乎很奇怪,并且想知道TThread代码的原作者是否有足够的理由来做这件事,原因是什么。 –

+1

@BlurrySterk因为在Delphi中事件处理程序通常在主线程中执行,这只是一致的。 – dummzeuch

+0

我个人认为TThread不在视觉/ VCL相关组件领域,并且看到DoTerminate是在线程的上下文中调用的,而且可以从另一个线程创建线程,在我看来,Synchronization是在这里并不是真正需要的默认行为。 –