Ok, disskutieren wir bissi
1. QThread muss in seinem destructor als Allererstes lediglich den quit() slot aufrufen (per signal) und mit this.wait() darauf warten, dass sein thread beendet ist.
der quit macht nur sinn, wenn der Thread in ner eventloop laeuft. also im run muss nen exec() aufgerufen werden.
Ich behaupt mal, nen grossteil aller Programme die QThread verwenden, werden keine eigene Eventloop haben ! Grossteil definier ich mal mit >60% ! oder lehn ich mich damit zu weit ausm fenster ?
Von denen die keine QT-Eventloop nutzen, denk ich mal, laufen paar einfach durch , und melden mit finished() dem erzeugenden thread das ... das wars.
Der Rest, denk ich mal iss auch ne Menge(um ned zu sagen eher der groesste Teil, weil threads die einfach auslaufen schlecht von aussen zu synchronisieren sind, d.h. die schlecht von user schlecht zu beenden sind), wird einfach traditionell in ner eigenen schleife laufen und ueber synchronisationsvariablen gesteuert. Funktioniert equivalent zu der eventloop, nur ist diese loop wahrscheinlich performanter, weil sie den QT ballast ned traegt, leute die ohne QT oder aehnliche Bibs Threads programmieren, kennen das eh ned anders, und leider eben das der Thread nicht durch quit() einfach zum anhalten gezwungen wird, sondern eben durch irgend was anderes .... das muesstest du dem DTor beibringen ! WIe wuerdest das machen ?
Also dein Vorgehen gaenge scho mal mit nem grossteil der Threads ned.
weiterhin:
Dtoren sind von natur aus sensibel
gibt ne ganze menge an literatur, warum dtoren keine exceptions werfen sollten ^^
und so nen sensibles ding willst in ne warteschleife schicken ?
was machst du bei, sagen wir etwas widerspenstigeren threads ... also threads die sich nicht so ohne weiteres beenden lassen, weil sie haengen z.b.
Willst den User das programm um die ohren fliegen lassem, ala wenn der thread ned geht, kann ich nix fuer
Grad wenn mit APIs zu spezieller hardware zu tun hasst, passiert das oefters ohne das was dazu kannst.
Die hohe Schule iss dann, nen thread mehrstufig zu beenden, ohne das dein Programm bockt ... aeh blockt.
Unter QT geht das recht human z.b. so:
du rufst das quit auf, oder setzt deine variable etc, also das, was deinen thread zum "aufgeben" bewegt.
Dann setzt dir nen timer .... und kehrst in die loop zurueck.(die App kann wieder nuetzliche aufgaben tun)
wenn dein thread sich normal beendet, sowas soll ja vorkommen,dann schickt er das finished. das holt deinen mainthread aus der eventloop, du setzt ne statusvariable, und gehst wieder in die loop zurueck. (jaja, damit die App weiter auf den user reagieren kann).
irgendwann iss dein timer faellig, du fliegst deswegen aus der loop.
du checkst die statusvariable, ob dein thread sich ned scho beendet hat, wenn ja iss alles ok, du kannst die ressourcen zum thread und alles rundherum loeschen.
Das ist der Normale weg, braucht zwar alles bissi (bis timer abgelaufen) aber die App hat in der Zeit nie geblockt. 99,9% der User sind zufrieden.
dann die unnormale variante.
Dein thread bockt, ergo nach dem timer hat das ding sich selber noch ned beendet. Du hasst allen grund ungeduldig zu sein !
Alternativ koenntest du hier noch paar sanftere methoden probieren, ... dem thread z.b. signale (keine QT signale, sondern OS Signale, ja auch das geht) schicken, wenn er denn drauf reagiert bzw dafuer programmiert ist ...
DU kannst auch gleich die harte variante waehlen.
Dein thread wird sich nie selber beenden, also zu besonderen mitteln greifen ! terminate (nein das schickst ned dem thread, sondern dem OS mit der threadId), dann nen wait mit nem timer triggern.
Richtig, hier blockiert deine GUI, wir haben aber auch ne aussnahmesituation.
laeuft der timer aus und ned das terminate, iss was ganz faul, deine chance das programm zu retten ist nahe NULL ... Hier waer es angebracht richtig boese Dinge zu tun (Core dump etc.)
zum glueck wird aber in den meisten faellen das terminate auslaufen, ergo dein thread iss zwar vom BS beendet worden, du hasst die ressourcen verloren, die der thread kontrollierte, die oxideiren nu im Speicher als Leichen rum (memory leaks), aber du kannst dein programm nach ner fehlermeldung (um den User angst einzujagen !) noch sauber beenden und ggf. Daten speichern.
Ergo von den 0,1% Usern sind vielleicht 90% dir ueberdankbar, das du trotz kritischer Fehlfunktion Ihre daten noch retten konnstest
Und sowas woelltest du alles in den DTor packen ???
Es gibt uebrigens noch paar Coding styles die zu beachten waeren.
deshalbdie Frage:
Warum willst du Bitte im Thread Instanzen dynamisch erzeugen, die nur fuer den Thread gelten (also so lange wie der leauft), und dann durch die Verwaltung mit dem Thread zusammen beenden.
nen thread iss nichts anderes wie eine Funktion, die parellel zu den anderen threads ausgefuehrt wird.
also es laeuft nur die run() methode durch.
Selbst wenn du ein exec() drinne aufrufst, aendert sich nix drann, nur das das ding da drinne in ner schleife haengt.
Also wenn du dem dem das quit schickst, kommt er aus dem exec() und laeuft bis zum ende der run durch.
Das heisst du kannst ohne weiteres instanzen vor dem exec anlegen, und die dann nach dem exec() wieder zu loeschen.
Wenn die signale empfangen sollen, muessen die QObjects sein, richtig.
Aber sie muessen um himmels willen nicht dynamisch angelegt sein ...
C++ grundRegel fuer den performance-bewussten programmierer:
auf den Stack was geht ! in den Heap/Freestore was muss !
oder anders, meide new (und malloc,alloc ... ham sowieso nix in c++ zu suchen)!
also du kannst in deinem Run durchauss sowas machen:
Code: Alles auswählen
QMyThread::run()
{
QMySignalReceiverIrgendwas sigreceiver;
connect(this,SIGNAL(terminated(),&sigreceiver,SLOT(makeBlueScreen()));
exec();
/// da sigreceiver lokal aufm Stack war, wird es hier automatisch ungueltig, die connections werden soweiso getrennt durch den DTOR ... alles super in ordnung.
}
Und Objecte die ueber die laufzeit des Threads hinaus brauchst, solltest sowieso an ner ganz anderen stelle erzeugen !
Ciao ....