QThread wann loeschen?

Alles rund um die Programmierung mit Qt
Antworten
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

QThread wann loeschen?

Beitrag 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
Esleborn
Beiträge: 265
Registriert: 27. Januar 2005 01:23
Wohnort: Baden-Würtenberg
Kontaktdaten:

Beitrag 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
Glaube an eine Lösung, nur dann kannst du auch eine finden.
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag 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
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Sicher kannst du jederzeit quit() im Slot aufrufen.
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag von ColonelMoW »

danke dir - das mit dem quit() funktionert

Col
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag 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.
Zuletzt geändert von ColonelMoW am 30. Mai 2008 18:20, insgesamt 1-mal geändert.
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag 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.
ColonelMoW
Beiträge: 30
Registriert: 15. April 2008 16:24

Beitrag 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
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag von Maxima »

Ich denke schon, probier es doch einfach...
Antworten