Seite 1 von 1

QThread wann loeschen?

Verfasst: 11. Mai 2008 14:22
von ColonelMoW
Einen schoenen Pfingstsonntag euch allen.

Ich brauch mal kurz Hilfe - steh auf dem Schlauch:
Wenn ich eine Klasse erstelle welche von QThread abgeleitet ist und ich dieser via exec() eine eigene Eventloop spendiere, gilt doch trotzdem weiterhin das Speicherverwaltungssystem von Qt - auch ueber Threadgrenzen hinaus, oder?

Ich erstelle ein Thread-Objekt auf dem Heap und gebe ihm ein Parent mit.
Wird das Parent geloescht so sorgt Qt dafuer, dass zuvor mein Thread geloescht wird, richtig? Oder hat das Parent keine Kontrolle mehr ueber sein Kind, wenn dieses eine eigene Eventloop hat?

Und noch was: Wann wird das finishd()-Signal bei Threads mit Eventloop emittiert? Ich habe in Daniel Molkentins Buch gesehen, dass er bei Threads ohne Eventloop deren finished()-Signal mit dem deleteLater()-Slot verbindet - ist ja eine gute Idee. Wenn ich nun einen Thread mit Eventloop habe, kann ich ja auch sein finished()-Signal mit dem deleteLater()-Slot verbinden. Nur wann wird finished emittiert? In der Doku steht:
"This signal is emitted when the thread has finished executing."
Wann ist denn ein Thread mit Eventloop "fertig"? Wenn ich den quit()-Slot aufrufe? Dieser haelt ja die Eventloop an, sprich die exec()-Funktion wird verlassen und man landet wieder in der run(). Sobald diese verlassen wird sollte doch finished() emittiert werden. Existiert denn beim Verlassen von run() das Objekt noch solange bis es jemand loescht? Sollte schon, oder?
Ich moechte nur vermeiden, dass sich lauter Thread-Objekte im Speicher ansammeln, die ich nichtmehr brauche.

Ich hoffe mir konnte jemand folgen! :oops:
Falls nicht bitte schreiben, dann werde ich das nochmal umschreiben....

Col

Verfasst: 11. Mai 2008 16:50
von Esleborn
hi,
soweit ich weiß, liegen QThread Objekte selbst im erzeugenden Thread und nicht in ihrem eigenen Thread. Das heißt, sie existieren unabhängig davon, ob ihr eigener Thread noch läuft oder nicht.
Damit wird der Thread gelöscht (und damit auch beendet...!), wenn das Parent des Threads gelöscht wird.
Das finished sollte emittiert werden, sobald die run fertig ist (nicht schon wenn die exec fertig ist) (also wie von dir angemerkt "kurz nach" bei quit, beachte bitte, dass das quit in dem Thread aufgerufen werden sollte, der das QThread erstellt hat bzw über Qt::QueuedConnection).
Verbindest du SIGNAL ( finished ( ) ) mit SLOT ( deleteLater ( ) ), so wird der QThread gelöscht sobald die ::run beendet ist.

Grüße
Chris

Verfasst: 12. Mai 2008 13:00
von ColonelMoW
Hi Chris,

Danke fuer die Antwort!
Sprich, wenn ich das SIGNAL(finished()) mit dem SLOT(deleteLater()) verbinde, wird das QThread-Objekt geloescht, sobald sich der Thread beendet (bzw. nachdem run() verlassen wird - unabhaenig davon ob sein Parent noch existiert oder nicht.

Den Thread beende ich, indem ich die Eventloop verlasse, also den SLOT(quit()) triggere. Kann der Thread auch selbst seinen SLOT(quit()) aufrufen?

Col

Verfasst: 12. Mai 2008 13:56
von upsala
Sicher kannst du jederzeit quit() im Slot aufrufen.

Verfasst: 13. Mai 2008 19:04
von ColonelMoW
danke dir - das mit dem quit() funktionert

Col

Verfasst: 30. Mai 2008 16:31
von ColonelMoW
Sorry, dass ich das Topic nochmal hochholen muss:

Ich erstelle ein QThread-Object (comm). Dann verbinde ich das finished()-signal mit dem deleteLater()-Slot. Schliesslich starte ich den Thread indem ich seine start()-Routine aufrufe:

Code: Alles auswählen

CommunicatorCall *comm = new CommunicatorCall(...);
   connect( comm, SIGNAL(finished()),
                comm, SLOT(deleteLater()), Qt::QueuedConnection);
   comm->start();
Das hat jetzt aber zur Folge, dass der quit()-slot des Threads nicht mehr von diesem selbst aufgerufen werde darf, ist das so richtig?
In der Qt-Doku steht bei deleteLater():
the control must return to the event loop from which deleteLater() was called.
Sobald der thread sein eigenes quit()-aufruft wird ja die event-Loop beendet. Damit wird finished()-emittiert was nun ja den Slot deleteLater() aufruft. Das Thread-Objekt wird aber erst geloescht, wenn zu der Event-Loop zurueckgekehrt wird, die den Slot aufgerufen hat. Das war ja die des Threads, und diese existiert ja schon nicht mehr.

Somit darf das garnicht gehen, richtig?
Oder habe ich etwas uebersehen?

Col

//----------------------------------------------------
edit: habe noch hinzugefuegt, dass comm das von QThread abgeleitete Objekt ist.

Verfasst: 30. Mai 2008 17:56
von Maxima
Ich bin mir nicht ganz sicher:

das connect, daß Du im parent geknüpft hast, existiert ja in der event-loop des parents und die arbeitet ja weiter...(das Signal kommt also am Slot an)

aber:

Code: Alles auswählen

void thread::run
{
        connect( this, SIGNAL(finished()),
                     this, SLOT(deleteLater()), Qt::QueuedConnection); 
exec();

}//<- hier wird das finished geschickt, daß nicht mehr zugestellt wird
dürfte nicht gehen, weil die verbindung auf den eventloop des Threads angewiesen ist.

So habe ich es verstanden, ein experten-feedback wäre aber klasse.

Verfasst: 30. Mai 2008 18:19
von ColonelMoW
Maxima hat geschrieben: ...

Code: Alles auswählen

void thread::run
{
        connect( this, SIGNAL(finished()),
                     this, SLOT(deleteLater()), Qt::QueuedConnection); 
exec();

}//<- hier wird das finished geschickt, daß nicht mehr zugestellt wird
dürfte nicht gehen, weil die verbindung auf den eventloop des Threads angewiesen ist.
Ist richtig. So geht das vermutlich auch nicht. Daher:
Ich erstelle das comm-object (das ist das von QThread abgeleitete). Dann
kommt der connect Aufruf noch ausserhalb vom Thread.
Und erst dann starte ich den thread indem ich sein start() aufrufe.
Also die QueuedConnection wird ausserhalb des Threads erstellt.
Geht das dann?

Col

Verfasst: 30. Mai 2008 18:23
von Maxima
Ich denke schon, probier es doch einfach...