1

我有一个TThread的后代和一个对象列表,每个对象都有自己的此类线程副本,但还有使用CreateEvent()API创建的Event对象。多线程的Delphi 7应用程序 - 应用程序终止的问题

不同的对象通过事件触发相互作用。即每个线程必须等待,直到其他线程将触发其事件。当然,有一个“主”线程永久工作,所以自我阻止永远不会发生。这个系统工作得很好,直到每个对象的Execute方法结束。

当我试图中断所有线程时,出现probkem,例如通过应用关闭。在这种情况下,我需要它调用终止每个线程的方法,一些外部函数:

for i := 0 to FLayers.Count - 1 do 
    begin 
    FLayers.Layer[i].FTerminating := true; 
    f := true; 
    while f do 
    begin 
     f := FLayers.Layer[i].IsActive; 
     if f then 
     begin 
     Sleep(100); 
     Application.ProcessMessages; 
     end; 
    end; 
    FLayers.Layer[i].FTerminating := false; 
    end; 

此功能坐落在Form.OnClose()事件。

的问题是关于两个线程都正常终止,但其他所有人都在WaitForSingleObject的()调用停止:

procedure TLayerThread.Execute; 
begin 
FLayer.FIsActive := true; 
............... 
repeat 
// 
if Terminated or 
    FLayer.FTerminating or 
    (FLayer.FEvent = INVALID_HANDLE_VALUE) then 
    begin 
    break; 
    end; 
// 
Fres := WaitForSingleObject(FLayer.FEvent, 100); <<<<<<<<<<<<<<<<<<<<<<<< 
until Fres <> WAIT_TIMEOUT; 
........... 
FLayer.FIsActive := false; 
end; 

的所有线程都只是在该行停止(挂起)。如上所示,尽管设置了超时值。

任何想法?

上午使用的是Delphi 7和Win XP。

在此先感谢。

Followup--

我发现这个问题是在Synchronize()调用覆盖从execute()方法中。我无法理解这里出了什么问题。 Synchronize()调用通常的东西,比如视觉控件更新等等。

正如调试器显示的那样,我的线程中有很多挂在WaitForSingleObject()调用上,但这不是我在Execute()方法中用于协调不同线程,而是另一个调用。我可以假设它是在这里:

class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord); 
................. 
     LeaveCriticalSection(ThreadLock); 
     try 
      WaitForSingleObject(SyncProc.Signal, INFINITE);<<<<<<<<<<<<<<<<<<<<<< 
     finally 
      EnterCriticalSection(ThreadLock); 
     end; 
.................. 

有没有人在那里,谁可以告诉我什么是我的代码错了?我从来没有听说过,这是不允许从内部调用同步()execute()方法...

回答

1

而不是WaitForSingleObject的你应该使用WaitForMultipleObjects的与无限超时和等待两个事件,您FLayer.FEvent和第二次终止事件。

AFAIR您必须为每个过程创建一个终止事件。 如果WaitForMultipleObjects返回循环的终止事件的ID。

在OnClose()方法中,您必须简单地指示所有终止事件。

+0

对不起,但是你有关过程终止事件吗?请注意,我不是关于进程终止。让我们把它看作是一个过程,中断所有的线程。例如。我有“停止处理”菜单项,它不关闭应用程序,但只是中断所有线程,就像上面显示的那样。而且我无法等待事件的发生,因为一般来说,每个线程都必须单独中断。简而言之,我的问题是“为什么一个线程终止会导致另一个线程挂起?”谢谢。 – Alex 2010-12-18 15:50:27

+0

如果你在OnClose()或其他方法中调用它,这无关紧要。通过为每个线程使用一个关闭事件,您还可以单独结束每个线程。 – Robert 2010-12-24 22:05:04