Thread-Klasse in Delphi
Raptor[Mental Studio]
http://mental.mentsu.com
dritte
Nachdem wir über den Konstruktor gesprochen haben, schauen wir uns den Destruktor an:
Destruktor TThread.Destroy;
beginnen
if (FThreadID <> 0) und nicht FFinished then
beginnen
Beenden;
wenn FCreateSuspended dann
Wieder aufnehmen;
WaitFor;
Ende;
wenn FHandle <> 0 dann CloseHandle(FHandle);
geerbt Zerstören;
FFatalException.Free;
RemoveThread;
Ende;
Überprüfen Sie vor der Freigabe des Thread-Objekts zunächst, ob der Thread noch ausgeführt wird (die Thread-ID ist nicht 0 und das Thread-Ende-Flag ist nicht gesetzt), um den Thread zu beenden. Der Terminate-Prozess setzt einfach das Terminated-Flag der Thread-Klasse, wie im folgenden Code:
PROcedure TThread.Terminate;
beginnen
FTerminated := True;
Ende;
Daher muss der Thread weiterhin ausgeführt werden, bis er normal endet, anstatt den Thread sofort zu beenden.
Hier ein kleiner Exkurs: Viele Leute haben mich gefragt, wie man einen Thread „sofort“ beenden kann (gemeint sind natürlich Threads, die mit TThread erstellt wurden). Natürlich funktioniert es nicht! Die einzige Möglichkeit, einen Thread zu beenden, besteht darin, die Ausführung der Execute-Methode abschließen zu lassen. Wenn Sie also möchten, dass Ihr Thread so schnell wie möglich beendet wird, müssen Sie im Allgemeinen innerhalb kurzer Zeit ständig das Terminated-Flag in der Execute-Methode überprüfen dass Sie rechtzeitig aussteigen können. Dies ist ein sehr wichtiges Prinzip beim Entwerfen von Thread-Code!
Wenn Sie in der Lage sein müssen, den Thread „sofort“ zu verlassen, ist die TThread-Klasse natürlich keine gute Wahl, denn wenn Sie die API verwenden, um den Thread zwangsweise zu beenden, wird das TThread-Thread-Objekt möglicherweise nicht korrekt freigegeben Eine Zugriffsverletzung tritt auf, wenn das Objekt zerstört wird. In diesem Fall können Sie zum Erstellen von Threads nur API- oder RTL-Funktionen verwenden.
Wenn sich der Thread in einem angehaltenen Startzustand befindet, versetzen Sie ihn in den laufenden Zustand und rufen Sie dann WaitFor auf, um zu warten. Seine Funktion besteht darin, zu warten, bis der Thread endet, bevor er mit der Ausführung fortfährt. Die Implementierung von WaitFor wird später erläutert.
Schließen Sie nach dem Ende des Threads den Thread-Handle (der Handle ist bei der normalen Thread-Erstellung vorhanden) und geben Sie das vom Betriebssystem erstellte Thread-Objekt frei.
Rufen Sie dann TObject.Destroy auf, um dieses Objekt und das abgefangene Ausnahmeobjekt freizugeben, und rufen Sie schließlich RemoveThread auf, um die Anzahl der Threads im Prozess zu reduzieren.
Andere Aspekte in Bezug auf Suspend/Resume und Thread-Prioritätseinstellungen stehen nicht im Mittelpunkt dieses Artikels und werden nicht noch einmal besprochen. Was im Folgenden besprochen wird, sind die beiden anderen Schwerpunkte dieses Artikels: Synchronize und WaitFor.
Bevor diese beiden Funktionen eingeführt werden, müssen jedoch zwei weitere Thread-Synchronisationstechnologien eingeführt werden: Ereignisse und kritische Abschnitte.
Ereignisse unterscheiden sich von Ereignissen in Delphi. Im Wesentlichen entspricht Event einer globalen booleschen Variablen. Es gibt zwei Zuweisungsoperationen: Setzen und Zurücksetzen, die dem Setzen auf Wahr oder Falsch entsprechen. Die Überprüfung seines Werts erfolgt durch die WaitFor-Operation. Entsprechend der Windows-Plattform gibt es drei API-Funktionen: SetEvent, ResetEvent und WaitForSingleObject (es gibt mehrere APIs, die die WaitFor-Funktion implementieren, dies ist die einfachste).
Diese drei sind Grundelemente, sodass Event Anwendungen in Multithreads implementieren kann, die allgemeine boolesche Variablen nicht können. Die Funktionen von Set und Reset wurden bereits erwähnt. Lassen Sie uns nun über die Funktion von WaitFor sprechen:
Die Funktion von WaitFor besteht darin, zu prüfen, ob der Status des Ereignisses der Set-Status ist (entspricht True). Wenn nicht, wird darauf gewartet, dass es in den Set-Status wechselt Thread, der WaitFor aufruft, befindet sich in einem angehaltenen Zustand. Darüber hinaus verfügt WaitFor über einen Parameter für die Timeout-Einstellung. Wenn dieser Parameter 0 ist, wird nicht gewartet, sondern der Ereignisstatus wird sofort zurückgegeben wartet auf die entsprechende Anzahl von Millisekunden und gibt dann den Status des Ereignisses zurück.
Wenn das Ereignis vom Status „Zurücksetzen“ in den Status „Festlegen“ übergeht, werden andere Threads aktiviert, die aufgrund des Ereignisses „WaitFor“ angehalten wurden. Aus diesem Grund wird es „Ereignis“ genannt. Das sogenannte „Ereignis“ bezieht sich auf „Zustandsübergang“. Diese „Zustandsübergangs“-Informationen können über Ereignisse zwischen Threads weitergegeben werden.
Natürlich kann eine ähnliche Funktion auch mit einer geschützten booleschen Variablen (siehe Einleitung zum kritischen Abschnitt weiter unten) erreicht werden, sofern WaitFor durch eine Codeschleife ersetzt wird, die den booleschen Wert überprüft. Funktionell gibt es überhaupt kein Problem, aber im tatsächlichen Gebrauch werden Sie feststellen, dass ein solches Warten viele CPU-Ressourcen beansprucht, die Systemleistung verringert und die Ausführungsgeschwindigkeit anderer Threads beeinträchtigt. Daher ist es unwirtschaftlich und manchmal sogar möglich Probleme. Es wird daher nicht empfohlen, es auf diese Weise zu verwenden.
(fortgesetzt werden)