Auf Thread ende warten
-
Hallo zusammen,
erst mal vielen Dank für die vielen Antworten.
Ich habe das ganze nun in einen TThread ausgelagert welcher auch wie gewünscht seine Arbeit tut.Allerdings habe ich nun immer noch das Problem, daß ich im GUI Thread abhänhgig vom Threadzustand ein "Ereignis" auslösen will.
Th69 schrieb:
... Man registriert sich bei dem Ereignis und die GUI läuft weiter. Und wenn das Ereignis eintritt, dann wird die Ereignismethode aufgerufen...
Ich denke, daß hier z.B. TEvent gemeint ist, allerdings wo ist die Ereignismethode welche den Code ausführt (soll in der Mainform Klasse sein)?
Ich kann das Event zwar Abfragen, jedoch dann wäre ich ja wieder beim pollen!?Irgendwie steh ich glaub gerade auf dem Schlauch, sorry.
MfG Stephan
-
Stephan schrieb:
Th69 schrieb:
... Man registriert sich bei dem Ereignis und die GUI läuft weiter. Und wenn das Ereignis eintritt, dann wird die Ereignismethode aufgerufen...
Ich denke, daß hier z.B. TEvent gemeint ist
Nein, ist es nicht, sondern
OnTerminate
. Th69 hat sogar darauf verlinkt.Außerdem habe ich dich auf zwei Methoden von
TThread
verwiesen und sogar ein vollständiges Beispiel in C++ verlinkt, das zeigt, wie man sie benutzt. Willst du dir das nicht mal anschauen?
-
Ich habe mir das ganze angeschaut und auch verwendet.
Vermutlich habe ich mich nicht richtig ausgedrückt, denn mein Problem hat sich etwas geändert.
Ich muß/will nicht mehr auf das Ende des Threads warten, sondern der Thread soll ein Ereignis im GUI Thread auslösen. Du wirst jetzt berechtigterweise sagen, verwende das von Dir verlinkte, jedoch dies setzt voraus, daß der Code in der Threadklasse implementiert ist.
Da ich jedoch auf mehrere GUI Element zugreifen muß hätte ich den Code gerne in der GUI Klasse (TForm) implementiert und aus dem TThread im GUI Thread Kontext ausgeführt.
Ich hoffe es ist nun klarer was ich will, jedoch ich vermute daß das ganze nicht wirklich funktioniert.MfG Stephan
-
Und genau dafür ist die Synchronize()-Funktion. Löse einfach dadrin ein Ereignis aus und in der entsprechenden Form-Funktion (welche sich auf dieses Ereignis reistriert hat), führst du die GUI-Aktionen aus...
-
Th69 schrieb:
Und genau dafür ist die Synchronize()-Funktion. Löse einfach dadrin ein Ereignis aus und in der entsprechenden Form-Funktion (welche sich auf dieses Ereignis reistriert hat), führst du die GUI-Aktionen aus...
Und falls dich das Wort "Ereignis" verwirrt: schau dir im verlinkten Beispiel die Funktion
AddNewNumberToMemo()
an, die anSynchronize()
übergeben wird. Die greift, wie du siehst, aufs GUI zu. Ebendiese Funktion könnte ja auch in deiner Formklasse stehen, wenn dir das lieber ist. Dann mußt du dir nur noch einen Weg überlegen, wie du die Form-Instanz in den Thread hineinbekommst.(ɹǝʇǝɯɐɹɐdɹoʇʞnɹʇsuoʞ slɐ :ʇɹoʍʇu∀)
-
@audacia: das halte ich für keine gute Lösung, daß der Thread die Form kennt (daher ja auch mein Vorschlag mit dem Ereignis
Hier ein Beispiel:
// in TThread-Klasse public: typedef void (__closure *TMyEvent)(); // <- evtl. noch Parameter hinzufügen TMyEvent OnAction; // in Execute Synchronize(CallActionEvent); // <- hier bin ich mir über die Syntax nicht eindeutig mehr sicher // Methode void CallActionEvent() { if (OnAction) OnAction(); }
Und dann von der Form-Klasse aus den Thread erzeugen und das Ereignis registrieren:
thread->OnAction = DoAction;
void MyForm::DoAction() { // hier der Zugriff auf die GUI }
Und bei zusätzlichen Ereignis-Parametern entsprechend die Ausdrücke in den leeren Klammern anpassen.
-
Th69 schrieb:
@audacia: das halte ich für keine gute Lösung, daß der Thread die Form kennt (daher ja auch mein Vorschlag mit dem Ereignis
Klar, mit Callback-Funktion ist es besser, und idealerweise sind GUI und Logik sowieso entkoppelt. Ich wollte nur erstmal den Erkenntnisprozeß ins Rollen bringen
Wenn man das schon mit einem gebundenen Callback macht, kann man den Weg auch noch weitergehen:
- das läßt sich offensichtlich verallgemeinern zu einer Hilfsfunktion, die zwei Callbacks annimmt: die eigentliche Aktion (die
Execute()
-Methode) und eine Benachrichtigungsroutine (dein Callback halt), die auf dem UI-Thread ausgeführt wird - dann ist natürlich die Frage, was passiert, wenn die Aktion eine Exception wirft; die sollte vielleicht an den Benachrichtigungs-Callback weitergegeben werden
- außerdem ist es ineffizient, für jede asynchrone Aufgabe einen Thread zu starten, weil Threads vergleichsweise teuer sind; also könnte man entweder einen Threadpool oder sowas wie
QueueUserAPC()
verwenden - später stellt man dann fest, daß es ganz nützlich wäre, wenn man mehrere Callbackfunktionen angeben könnte, die aufgerufen werden, wenn die Aktion erfolgreich war
Kurzum, langfristig baut man damit die TPL nach. Deshalb auch mein Verweis auf die Parallel Programming Library; wenn du es richtig machen willst, dann spar dir das Neuerfinden des Rads und nimm die.
- das läßt sich offensichtlich verallgemeinern zu einer Hilfsfunktion, die zwei Callbacks annimmt: die eigentliche Aktion (die
-
Hallo zsuammen,
nochmals vielen dank für die Ideen und die angeregte Diskussion.
audacia schrieb:
Dann mußt du dir nur noch einen Weg überlegen, wie du die Form-Instanz in den Thread hineinbekommst.
(ɹǝʇǝɯɐɹɐdɹoʇʞnɹʇsuoʞ slɐ :ʇɹoʍʇu∀)Das ist im Prinzip was ich teilweise jetzt schon machen, ist mir jedoch "zu aufwendig", da ich auf viele verschiedene GUI Elemente zugreifen muß.
Außerdem ist das ganze noch eine Basisklasse die in vielen verschiedenen Anwendungen weiter vererbt wird, deshalb ist mir hier der Aufwand eigentlich zu groß.Th69 schrieb:
@audacia: das halte ich für keine gute Lösung, daß der Thread die Form kennt (daher ja auch mein Vorschlag mit dem Ereignis
Irgendwie hat mich die Bezeichnung Ereignis auf den falschen "Weg" geführt, das damit im Endeffekt ein Callback gemeint war, darauf bin ich komischerweise nicht gekommen
Ich denke ich werde dies zuerst mal mit einem Callback lösen und mir langfristig die von audacia angesprochenen Punkte genauer anschauen.
MfG Stephan
-
Vllt. bin ich schon zu C# verwöhnt, daß ich dazu Ereignis (anstatt Callback) sage.
-
Th69 schrieb:
Vllt. bin ich schon zu C# verwöhnt, daß ich dazu Ereignis (anstatt Callback) sage.
Da wäre Delegate naheliegender