[gelöst]QThread finished Signal wird nicht ausgelöst
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Das moveToThread im ctor bringt gar nichts (zum x. Mal). Es muss in die run() - Methode da nur dort der neu erzeugte Thread läuft!
Da Du dies nicht machst wird auch der wiederholen() - Slot im Hauptthread ausgeführt. this ist ja immer noch im Hauptthread also ...
Da Du dies nicht machst wird auch der wiederholen() - Slot im Hauptthread ausgeführt. this ist ja immer noch im Hauptthread also ...
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
Das Problem ist eben das es hängt wenn es auserhalb vom Konstruktor ist.Christian81 hat geschrieben:Das moveToThread im ctor bringt gar nichts (zum x. Mal). Es muss in die run() - Methode da nur dort der neu erzeugte Thread läuft!
Da Du dies nicht machst wird auch der wiederholen() - Slot im Hauptthread ausgeführt. this ist ja immer noch im Hauptthread also ...
Wenn ich es in die Run- Methode mache --> hängt die Gui
Code: Alles auswählen
void Thread::run(){
this->moveToThread(this);
isClose=false;
noneThread = new NonThread();
connect(noneThread, SIGNAL(senden()), this, SLOT(wiederholen()), Qt::QueuedConnection);
exec();
}
Thread::Thread(){
}
void Thread::wiederholen(){
qDebug() << "Wiederholen";
if(isClose){
this->quit();
return;
}
this->sleep(2);
noneThread->sendenbegin();
}
void Thread::requestClose(){
qDebug() << "request close";
isClose= true;
}
Thread::~Thread(){
qDebug() << "thread gelöscht";
noneThread->deleteLater();
}
QObject::moveToThread: Current thread (0x3e4ed0) is not the object's thread (0x9527e88).
Cannot move to target thread (0x9527e88)
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Doku und so...
http://doc.trolltech.com/4.4/qthread.html#currentThread
http://doc.trolltech.com/4.4/qthread.html#currentThread
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
Entweder bin ich komplett übermüdet oder du liegst (ausnahmsweise) falsch. Bei moveToThread muss der aktuelle Thread(-Kontext) und die Threadzugehörigkeit gleich sein. Diese Bedingung ist ausserhalb der run-Methode erfüllt. Beispiel:Christian81 hat geschrieben:Das moveToThread im ctor bringt gar nichts (zum x. Mal). Es muss in die run() - Methode da nur dort der neu erzeugte Thread läuft!
Da Du dies nicht machst wird auch der wiederholen() - Slot im Hauptthread ausgeführt. this ist ja immer noch im Hauptthread also ...
Code: Alles auswählen
MyThread *t = new MyThread()
// Aktueller Kontext ist der main-Thread ("GUI")
// Aktuelle Zugehörigkeit von t ist der Eventloop der GUI
t->moveToThread(t); // Verschiebe Instanz t in den Eventloop von t. OK
Jedoch:
Code: Alles auswählen
void MyThread::run()
{
// aktueller Kontext ist t
// aktuelle Zugehörigkeit von t ist der GUI-Thread, daher:
moveToThread(this); // illegal, weil "it cannot "pull" an object from any arbitrary thread to the current thread."
..
}
Zu den anderen Problemen:
Warum Blockade ohne "moveToThread":
Das ist doch ganz logisch:Wenn ich diesen Befehl im Konstruktor weglasse wird die Gui Blockiert. Mir ist aber nur halb klar warum. Ich nehme an das durch das aufrufen der Unterklasse der Kontext im MainThread liegt und deswegen die Gui Blockiert. Also notwendig??
* Die Instanz von "Thread" lebt ohne moveToThread im GUI-Thread
* Die Instanz von "NonThread" lebt in "Thread".
* Wenn also NonThread ein Signal an "Thread" absetzt, wird dieses im Hauptthread verarbeitet:
Code: Alles auswählen
int main(...)
QApplication app....
app.exec(); // HIER
Warum Memoryleack MIT moveToThread:
Auch das ist doch vollkommen logisch:--> Funktioniert jedoch nicht! Sprich Boolean wird gesetzt aber kein finished() Signal gesendet bzw Destruktor aufgerufen.
* mit moveToThread im CTor verarbeitet die Instanz von "Thread" alle Events im eigenen Eventloop:
Code: Alles auswählen
void Thread::run()
{
...
exec(); // HIER
}
Ich habe es nicht getestet, aber ich vermute ein "moveToThread(QApplication::instance()->thread());" gleich nach "exec()" bringt auch nichts mehr (Doku: Note that any new events that are posted to this object will be handled in the targetThread., da steht nichts von den alten "pending" Events..).
Daher: ein Thread welcher bei sich selbst lebt kann kein Selbstmord begehen. Du wirst in der GUI auf das "finished()"-Signal reagieren und dort den Thread löschen müssen.
Weiters: Wenn du von Adam und Eva beginnst und momentan gerade die Architektur festlegt, solltest du unbedingt gut durchlesen: Blog You're doing it wrong
hth.
[EDIT]
Code: Alles auswählen
Thread::~Thread(){
qDebug() << "thread gelöscht";
noneThread->deleteLater();
}
Zuletzt geändert von solarix am 24. August 2010 12:46, insgesamt 1-mal geändert.
-
Christian81
- Beiträge: 7319
- Registriert: 26. August 2004 14:11
- Wohnort: Bremen
- Kontaktdaten:
Den Thread kennt er schon - hilft nur nichts.
Und mit dem moveToThread hast Du recht. Habe mir gerade den Sourcecode mal angeschaut. Das verwirrt aber den geneigten Anfänger noch mehr *grml*
Mein Standpunkt war dass der Thread ja erst innerhalb der run() - Methode existiert. Deshalb dürfte ein moveToThread() im ctor nicht funktionieren. Ein moveToThread macht aber nichts mit dem Thread sondern ist quasi nur eine Zuweisung zu einem QThread-Objekt - egal ob der Thread schon vorhanden ist, existiert oder schon tot ist. Dessen war ich mir nicht bewusst. Und deshalb funktioniert es schon im ctor und man kann, wie Du sagtest ein QObject nur von seinen aktuellen in einen anderen QThread schieben, nicht andersrum
Dafür muss ich noch'n Bier trinken ... shit
/edit: Und das schlimmste ist... ich glaube ich habe es an einer Stelle auf Arbeit genau so falsch gemacht wie ich oben behauptete... *argh*
Und mit dem moveToThread hast Du recht. Habe mir gerade den Sourcecode mal angeschaut. Das verwirrt aber den geneigten Anfänger noch mehr *grml*
Mein Standpunkt war dass der Thread ja erst innerhalb der run() - Methode existiert. Deshalb dürfte ein moveToThread() im ctor nicht funktionieren. Ein moveToThread macht aber nichts mit dem Thread sondern ist quasi nur eine Zuweisung zu einem QThread-Objekt - egal ob der Thread schon vorhanden ist, existiert oder schon tot ist. Dessen war ich mir nicht bewusst. Und deshalb funktioniert es schon im ctor und man kann, wie Du sagtest ein QObject nur von seinen aktuellen in einen anderen QThread schieben, nicht andersrum
Dafür muss ich noch'n Bier trinken ... shit
/edit: Und das schlimmste ist... ich glaube ich habe es an einer Stelle auf Arbeit genau so falsch gemacht wie ich oben behauptete... *argh*
MfG Christian
'Funktioniert nicht' ist keine Fehlerbeschreibung
'Funktioniert nicht' ist keine Fehlerbeschreibung
Exakt.. falls es dich beruhigt: ein Artikel im Linux-Magazin vor ein paar Wochen über genau dieses Thema war auch Schrott..Christian81 hat geschrieben:[...]Ein moveToThread macht aber nichts mit dem Thread sondern ist quasi nur eine Zuweisung zu einem QThread-Objekt - egal ob der Thread schon vorhanden ist, existiert oder schon tot ist.
[...]
Naja, bis jetzt scheint's niemand bemerkt zu habenChristian81 hat geschrieben: /edit: Und das schlimmste ist... ich glaube ich habe es an einer Stelle auf Arbeit genau so falsch gemacht wie ich oben behauptete... *argh*
Jetzt erzähl uns bloss nicht, dass das eine Strafe für dich wäreChristian81 hat geschrieben: Dafür muss ich noch'n Bier trinken
Danke für die Antworten und den Link, hat mich weitergebracht.
Habe jetzt eine Worker Klasse Implementiert und diese mit moveToThread dem thread hinzugefügt. Dann hatte ich noch die Probleme das der Konstruktor der Worker Klasse im Thread der Main Applikation war.. Eine richtige Lösung dafür habe ich nicht gefunden aber durch implementierung der wichtigsten funktionen außerhalb des Konstruktors konnte ich das Problem übergehen.
Gruß Alex
Habe jetzt eine Worker Klasse Implementiert und diese mit moveToThread dem thread hinzugefügt. Dann hatte ich noch die Probleme das der Konstruktor der Worker Klasse im Thread der Main Applikation war.. Eine richtige Lösung dafür habe ich nicht gefunden aber durch implementierung der wichtigsten funktionen außerhalb des Konstruktors konnte ich das Problem übergehen.
Gruß Alex