In einem gegebenen Beispiel erhalte ich eine Ausnahme beim Aufruf von AThread.Free.
Ich habe zwei Fragen:
Wie soll ich AThread
instance von TThread
in einem gegebenen Beispiel freigeben?
Ich verstehe nicht, warum TThread.Destroy
vor dem Destroying Resume
aufruft. Was ist der Sinn dieses?
Sie können FreeOnTerminate
nicht auf True
und auf Free
in der Thread-Instanz festlegen. Du musst das eine oder das andere machen, aber nicht beides. Wie es aussieht, zerstört dein Code den Thread zweimal. Sie dürfen ein Objekt niemals zweimal zerstören und natürlich, wenn der Destruktor zum zweiten Mal ausgeführt wird, treten Fehler auf.
Was passiert, ist, dass nichts passiert, seit Sie den Thread suspendiert haben, bis Sie den Thread explizit freigeben. Wenn Sie das tun, setzt der Destruktor den Thread fort und wartet darauf, dass er abgeschlossen wird. Dies führt dazu, dass Free
erneut aufgerufen wird, weil Sie FreeOnTerminate
auf True
setzen. Dieser zweite Aufruf von Free
schließt das Handle. Dann kehren Sie zum Thread-Prozess zurück und rufen % co_de auf % Dies schlägt fehl, weil das Handle des Threads geschlossen wurde.
Wie Martin in dem Kommentar erwähnt, dürfen Sie ExitThread
nicht direkt erstellen, da die Methode TThread
abstrakt ist. Außerdem sollten Sie TThread.Execute
nicht verwenden, was veraltet ist. Verwenden Sie Resume
, um mit der Ausführung eines unterbrochenen Threads zu beginnen.
Persönlich möchte ich nicht Start
verwenden. Wenn diese Funktion verwendet wird, wird der Thread in einem anderen Thread zerstört, aus dem er erstellt wurde. Sie verwenden es normalerweise, wenn Sie die Instanzreferenz vergessen möchten. Das lässt Sie dann unsicher, ob der Thread zerstört wurde, wenn Ihr Prozess beendet wird, oder ob er sich selbst beendet oder während der Prozessbeendigung freigibt.
Wenn Sie FreeOnTerminate
verwenden müssen, müssen Sie sicherstellen, dass Sie FreeOnTerminate
nicht aufrufen, nachdem Sie Free
auf FreeOnTerminate
gesetzt haben. Die naheliegende Lösung besteht also darin, True
unmittelbar nach dem Aufruf von FreeOnTerminate
auf True
zu setzen und dann die Thread-Instanz zu vergessen. Wenn Sie Ausnahmen haben, bevor Sie zum Start bereit sind, können Sie den Thread sicher freigeben, da Sie Start
an diesem Punkt immer noch FreeOnTerminate
haben.
Ein eleganterer Ansatz wäre, die gesamte Initialisierung in den Konstruktor False
zu verschieben. Dann würde der Code wie folgt aussehen:
Die Situation ist in Ihrem Fall sehr kompliziert.
Erstens, Sie befreien einen suspendierten Thread nicht wirklich. Ein Thread wird in destructor fortgesetzt:
%Vor% Da Terminate
vor Resume
aufgerufen wird, wird die Methode Execute
niemals ausgeführt, und der Thread wird sofort beendet, nachdem er fortgesetzt wurde:
Sieh dir nun die letzte Zeile an - du rufst destructor ( Thread.Free
) vom Destruktor selbst auf!
Fantastischer Fehler!
Um Ihre Fragen zu beantworten:
FreeOnTerminate:= True
in Ihrem Code nicht verwenden; DoTerminate
method) sollte im Thread-Kontext while ausgeführt werden
Thread wird beendet. Sie können eine Feature-Anfrage an QC senden: Fügen Sie FFreeOnTerminate:= False
zu TThread.Destroy
implementation:
Das sollte einen rekursiven Destruktor-Aufruf verhindern und Ihren Code gültig machen.
Tags und Links delphi exception delphi-2009 tthread