1

Ich habe einen Nachkommen von TThread und eine Liste von Objekten, jedes mit seiner eigenen Kopie von diesem Thread und noch das Ereignis-Objekt, mit CreateEvent() API erstellt.Multithread Delphi 7 App - ein Problem mit App-Beendigung

Verschiedene Objekte interagieren durch Ereignisauslösung miteinander. I.e. Jeder Thread muss warten, bis ein anderer Thread sein Ereignis auslöst. Natürlich gibt es einen "Master" -Thread, der permanent funktioniert, so dass Selbstblockierung niemals passieren könnte. Dieses System funktioniert problemlos bis zum Ende der Execute-Methode in jedem Objekt.

Das Probkem erscheint, wenn ich versuche, alle Threads zu unterbrechen, z. durch Schließen der App In diesem Fall muss ich einige externe Funktion, welche Methode jedes Gewinde Terminate Anrufe:

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; 

Diese Funktion setzt sich in Form.OnClose() Ereignis.

Das Problem ist, dass etwa zwei Threads normal beendet werden, aber andere sind alle an der WaitForSingleObject() Aufruf gestoppt:

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; 

Alle Fäden sind nur gestoppt (Hang) auf der ganzen Linie. oben markiert, obwohl der Timeout-Wert eingestellt ist.

Irgendwelche Ideen?

Bin mit Delphi 7 und Win XP.

Vielen Dank im Voraus.

Followup--

Ich habe festgestellt, dass das Problem in der Synchronisation() Aufruf von innerhalb der Methode Execute() abgedeckt ist. Ich kann nicht verstehen, was hier falsch ist. Synchronize() ruft übliche Dinge wie Visual Controls auf und nicht mehr.

Wie der Debugger zeigt, hängen keine meiner Threads an einem WaitForSingleObject() -Aufruf, aber das ist nicht das, was ich in der Execute() -Methode verwende, um verschiedene Threads zu koordinieren, sondern einen anderen Aufruf. Ich kann annehmen, dass es hier ist:

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

Gibt es jemanden da draußen, wer könnte mir sagen, was in meinem Code falsch ist? Ich habe nie gehört, dass es nicht erlaubt ist, synchronisieren() aufrufen aus Execute() Methode ...

Antwort

1

Statt WaitForSingleObject Sie WaitForMultipleObjects mit Endlos-Timeout und wartet zwei Ereignisse verwenden sollten, Ihre FLayer.FEvent und ein zweites Kündigungsereignis.

AFAIR Sie müssen ein Abschluss-Ereignis pro Prozess erstellen. Wenn WaitForMultipleObjects die ID des Beendigungsereignisses zurückgibt, wird die Schleife beendet.

In der OnClose() - Methode müssen Sie einfach alle Terminierungsereignisse signalisieren.

+0

Es tut mir leid, aber sind Sie über eine Prozessbeendigung Ereignis? Bitte beachten Sie, ich bin nicht über eine Prozessbeendigung. Betrachten wir es als eine Prozedur, die alle Threads unterbricht. Z.B. Ich habe den Menüpunkt "Stop Processing", der die App nicht schließt, sondern nur alle Threads unterbricht, wie oben gezeigt. Und ich kann nicht unendlich auf das Ereignis warten, weil im Allgemeinen jeder Thread individuell unterbrechbar sein muss.Kurz gesagt war meine Frage: "Warum führt ein Thread-Terminierung zu einem anderen Thread hängen?" Vielen Dank. – Alex

+0

Es spielt keine Rolle, ob Sie es in OnClose() oder in einer anderen Methode aufrufen. Indem Sie ein Close-Event pro Thread verwenden, können Sie jeden Thread auch einzeln beenden. – Robert