Demonstration verschiedener Möglichkeiten, Threads in Delphi zu verwenden

Viel zu viele Delphi -Benutzer machen den Fehler, zu denken, dass ein Thread eine Art Magie ist, die die Leistung ihrer Anwendung verbessert. Leider ist dies alles andere als wahr. Der größte Fehler #1 beim Versuch, einen Thread zu implementieren, besteht darin, direkt auf visuelle Steuerelemente der Anwendung zuzugreifen. Diese visuellen Steuerelemente können jedoch nur im Kontext des Hauptfadens der Anwendung funktionieren. Die Verwendung eines anderen Threads zum Aktualisieren der Steuerelemente in der Benutzeroberfläche muss sehr sorgfältig geplant und implementiert werden. Und in den meisten Fällen ist es wahrscheinlich überhaupt nicht die richtige Lösung für das Problem.
Einfach ausgedrückt ist das VCL -Framework von Delphi nicht fadensicher. Während es viele Möglichkeiten gibt, einen Thread in Ihre Benutzeroberfläche zu integrieren, gibt es keine einzelne Einheit-Lösung. Es wird immer variieren, je nachdem, was Sie erreichen möchten. Meistens wollen die Menschen eine bessere Leistung (Geschwindigkeit) erzielen. Aber das wird sehr selten durch die Verwendung eines Threads getan. Stattdessen besteht die häufigste Szenarien, in denen ein Thread in eine Benutzeroberfläche integriert ist, darin, diese Benutzeroberfläche während einer langen Aufgabe zu reagieren.
Dazu stellen wir uns eine einfache Anwendung mit nur einer einzelnen Schaltfläche vor, die beim Klicken eine Datei aus dem Internet herunterlädt. Die Anwendung hat bereits einen Hauptfaden, der für die gesamte Benutzeroberfläche verwendet wird. Auf der Windows -Plattform bedeutet dies, Windows -Nachrichten zu senden/empfangen, an eine Steuereleinwand zu zeichnen, die Benutzerinteraktion zu erkennen usw. Dieser Thread ist im Wesentlichen eine riesige Schleife, die sich sehr schnell dreht. Für jede Revolution dieses sich drehenden Threads werden bestimmte Codesteile ausgeführt.
In einer einzelnen Thread -Umgebung würde dieser Datei -Download diese Schleife vom Drehen blockieren, bis der Download fertig ist. Während dieser Zeit kann dieser Thread keine UI -Updates mehr durchführen, Benutzerklicks oder irgendetwas erkennen. Dies ist es, was Windows dazu bringt, in den Titel solcher Formen zu stecken (nicht zu antworten), denn genau wie es heißt, reagiert es nicht.
Hier kommen zusätzliche Themen ins Spiel. Es muss auf Windows reagieren. Anstatt den Haupt -UI -Thread mit diesem riesigen Datei -Download zu blockieren, können Sie diese Datei -Download in einen anderen Thread einfügen. Es ist einfach so einfach, oder?
Sie können sich fragen: "Wie überwachte ich den Fortschritt?" oder "Wie werde ich benachrichtigt, wenn es fertig ist?" Dies würde bedeuten, dass der Download -Thread irgendwie mit dem Haupt -Thread interagieren muss. Genau hier kommt die Verwirrung ins Spiel. Ein Thread kann nicht einfach einen anderen Thread beeinträchtigen, da es nicht aussagekräftig ist, zu welchem Punkt ein Thread tatsächlich ist. Es gibt jetzt zwei separate Loops, und wenn Sie die Benutzeroberfläche aktualisieren möchten, kann dieser UI -Thread überall sein, was etwas tut. Angenommen, der Haupt -UI -Thread ist dabei, eine Zeichenfolge in dieselbe Steuerelement zu schreiben, in die auch Ihr anderer Thread schreiben möchte. Jetzt haben Sie zwei Themen, die versuchen, an dieselbe Speicheradresse zu schreiben, was zu unvorhersehbaren Problemen führen kann.
Durch Synchronisieren. Die Thread -Klasse von Delphi verfügt über eine Methode synchronize (), mit der ein Thread nur in einem Moment mit dem Haupt UI -Thread interagiert, wenn er sich tatsächlich richtig verhalten wird, wenn er tatsächlich ein solches Vorschlag erwartet. Der Code, der aus einem anderen Thread synchronisiert wird, läuft nicht tatsächlich im Kontext dieses Threads - er wird immer im Kontext des Haupt UI -Thread ausgeführt. Das ist die Idee von synchronize (), um Code im UI -Thread auszuführen.
Am Ende verwenden Sie die VCL nicht aus dem Thread. Stattdessen sendet Ihr Thread ein Signal an den Haupt Thread, und nur wenn der Haupt -Thread fertig ist, wird dieser Code ausgeführt. In der Zwischenzeit wird Ihr Sekundärfaden blockiert, während er darauf wartet, dass der Hauptfaden fertiggestellt wird.
Dann gibt es den Fehler, zu denken, dass eine große UI -Operation in einem Thread besser dran wäre. Angenommen, Sie haben eine Liste, auf der Sie Millionen von Artikeln bevölkern möchten. Das wird natürlich einige Zeit dauern, und während dieser Zeit wird Ihre Bewerbung nicht antworten. Wieder. Verschieben Sie diesen Code also einfach in einen Thread, oder?
Auch hier muss jede UI -Interaktion aus dem Hauptfaden und nur aus dem Hauptfaden durchgeführt werden. Themen sind nützlich, wenn Sie langwierige Berechnungen durchführen, massive Datenmengen verarbeiten, auf eine Antwort von einer Remote -Ressource oder auf andere Weise irgendetwas warten müssen, was sowohl zeitaufwändig als auch nicht direkt mit der Benutzeroberfläche zusammenhängt.
Das ist schwer zu sagen. Es gibt jedoch eine gängige Praxis, die beim Schreiben eines Threads stark empfohlen wird: Legen Sie Ihren Threadcode in eine eigene Einheit. Diese Einheit sollte von jeder anderen UI -Einheit isoliert werden. Es sollte nicht einmal eine VCL -verwandte Einheit in seiner Verwendungsklausel haben. Der Thread sollte nicht einmal wissen, wie er verwendet wird. Es sollte im Wesentlichen ein Dummy sein, um Ihre lange Aufgabe auszuführen. Wenn es um UI -Updates aus einem Thread geht, wird dies am besten durch synchronisierte Ereignisse erreicht.
Genau wie es sich anhört. Es ist ein Ereignis, das synchronisiert ist, wie bereits erläutert. Ein Ereignis ist einfach ein Zeiger auf eine Prozedur, die Sie dem Thread zuweisen können, bevor er beginnt. Wenn Sie im Thread die Benutzeroberfläche aktualisieren müssen, verwenden Sie Synchronize (), um dieses Ereignis auszulösen. Mit diesem Design müsste der Thread niemals wissen, dass er sogar von einer Benutzeroberfläche verwendet wird. Gleichzeitig erreichen Sie auch versehentlich Abstraktion. Der Faden wird wiederverwendbar. Sie können es an ein anderes Projekt anschließen, das möglicherweise nicht einmal über eine Benutzeroberfläche verfügt (sagen wir einen Windows -Dienst).
Hier finden Sie einige direkte Links zu verwandten Ressourcen zur Sicherheit von VCL -Threads, falls Sie nicht suchen möchten ...
Diese Anwendung zeigt die Verwendung von Threads in Delphi. Da es viele verschiedene Dinge zu wissen gibt, sind sie für verschiedene Zwecke in verschiedene Abschnitte unterteilt. Jedes Thema verfügt über mindestens 1 Formulareinheit (in ein Registerkartenblatt eingebettet) und mindestens 1 eigenständiger Einheit, die ihre Funktionalität neben der Benutzeroberfläche enthält. Dies geschieht absichtlich, um zu zeigen, dass Threads von jeder Benutzeroberfläche isoliert werden sollten .
Die Hauptform selbst enthält eigentlich keine Logik. Alles, was es tut, ist die Formulare in Registerkarten einbettet. Im Ereignishandler FormCreate() enthält es zahlreiche Aufrufe an EmbedForm() , die ein Formular für jedes Registerkarte Blatt instanziiert.
Die Verwendung der Anwendung ist sehr einfach. Sie navigieren einfach zu einem der Registerkarten, und jeder hat seine eigenen Anweisungen.


Zeigt, wie eine Datei in einem Thread aus dem Internet heruntergeladen werden kann. Es gibt eine einzelne universelle Funktion definierte DownloadFile() , die den Download ausführt. Die Benutzeroberfläche hat 3 Knöpfe:
Standardmäßig ist die zu heruntergeladene URL eine Testdatei von Thinkbroadband.com, aber Sie können jede von Ihnen gewünschte URL verwenden. Sie können auch den Speicherort auswählen, um die Datei zu speichern. Dies ist eine sehr einfache Demo, daher muss der Dateiname/die Erweiterung des lokalen Dateinamens an Ihre Anforderungen angepasst werden - sie ändert sich nicht automatisch für die von Ihnen heruntergeladene URL (wie die Browser normalerweise).

Zeigt an, wie Sie eine Fortschrittsleiste von einem Thread aktualisieren, der eine lange Aufgabe ausführt.

Demonstriert die Verwendung einer Datenbankverbindung in einem Thread und synchronisierte Daten mit dem UI -Thread.

Demonstriert mehrere Fäden, die massive CPU -Zyklen verbrauchen, um Ihren Prozessor zu testen.