Seite 1 von 1

Thread terminiert nicht

Verfasst: 9. September 2009 16:22
von Delryn
Hallo,

ich kann mir gerade nicht erklären wieso mein QThread sich nicht beendet. Für jede Vermutung bin ich dankbar.

In der run()-Methode wird auf eine abort-Variable geprüft, so das mit break aus der while(true)-schleife gesprungen wird

Lösche ich jetzt meinen QThread, so sieht der Destruktor wie folgt aus

Code: Alles auswählen

if (isRunning())
{   
	Abort(); // Setzt die boolesche Variable m_Abort
}
       
       
wait(); // verursacht einfrieren
// Deletekram
Dann hab ich ein paar Ausgaben in die while(true)-Schleife gepackt, weil ich wissen wollte, wieso er sie nicht verlässt. Na ja, es wird in dieser Schleife eine reguläre von mir geschriebene Methode der Threadklasse aufgerufen:
while(true)
{
if(m_Abort)
{
emit VideoStopped();
break;
}

if(m_pImgSource)
{

if(!ReadNextFrame() ) // hier geht's nicht weiter
{
Wenn ich in ReadNextFrame nochmals auf !m_Abort prüfe und ggfs. sofort return(false) zurückliefere ändert das gar nichts.


Vlt. hat ja jemand so ermstal eine Idee dazu.

Verfasst: 9. September 2009 16:42
von Mani99
Vielleicht ist es hilfreich wenn du noch etwas mehr code zeigst als ein paar while schleifen?

Verfasst: 9. September 2009 17:06
von pfid
Hab ich das richtig verstanden, du willst den Thread beenden indem du

Code: Alles auswählen

delete thread;
aufrufst? :shock:

Verfasst: 10. September 2009 09:43
von Delryn
pfid hat geschrieben:Hab ich das richtig verstanden, du willst den Thread beenden indem du

Code: Alles auswählen

delete thread;
aufrufst? :shock:

In der Klasse wo er benutzt wird hatte ich das vor. Im Destruktur wollte ich dann mit Abort() und wait() arbeiten, ich hab das jetzt aber in die Klasse die den Thread besitzt verlagert.

Dort sage ich quasi Abort() und dann wait(), damit er solange hängt bis die run-Methode beendet ist.

Danach sage ich delete thread.

Was noch zu beachten ist: Bei signal-Slot Geschichten kann es zu einem Hänger kommen, ich musste nochmal extra auf die Abort-Variable prüfen.

Verfasst: 10. September 2009 10:35
von Christian81
Delryn hat geschrieben: Was noch zu beachten ist: Bei signal-Slot Geschichten kann es zu einem Hänger kommen, ich musste nochmal extra auf die Abort-Variable prüfen.
Ich würde eher sagen - da fehlt ein wenig C++ Kenntnisse und es funktioniert nur durch Zufall.

Code: Alles auswählen

while(true)
{
  if(m_Abort)
  {
    break;
  }
}
Der Compiler sieht hier dass sich innerhalb der Schleife m_Abort nie ändern kann. Deshalb wird sein Optimierungsalgorithmus ziemlich sicher auf die Idee kommen das ganze wegzuoptimieren.
Also entweder die Variable als 'volatile' deklarieren oder was gescheites mit einer QSemaphore zu machen...

Verfasst: 10. September 2009 11:27
von Delryn
Christian81 hat geschrieben:
Delryn hat geschrieben: Was noch zu beachten ist: Bei signal-Slot Geschichten kann es zu einem Hänger kommen, ich musste nochmal extra auf die Abort-Variable prüfen.
Ich würde eher sagen - da fehlt ein wenig C++ Kenntnisse und es funktioniert nur durch Zufall.

Code: Alles auswählen

while(true)
{
  if(m_Abort)
  {
    break;
  }
}
Der Compiler sieht hier dass sich innerhalb der Schleife m_Abort nie ändern kann. Deshalb wird sein Optimierungsalgorithmus ziemlich sicher auf die Idee kommen das ganze wegzuoptimieren.
Also entweder die Variable als 'volatile' deklarieren oder was gescheites mit einer QSemaphore zu machen...

Warum sollte er das wegoptimieren?

m_Abort ist eine Membervariable der Klasse. Die kann ja sonstwo geändert werden. Z.B. von außen durch den Aufruf m_Abort.

Das funktioniert schon korrekt so.

Verfasst: 10. September 2009 11:31
von pfid
An deiner Stelle würd ichs so machen:

Code: Alles auswählen

{
   while (!m_abort)
   {
      ...
   }
}

Code: Alles auswählen

void abort() { m_abort = true; }

Code: Alles auswählen

{
   myThread->abort();

   if (! myThread->wait(5))
      myThread->terminate();

   delete myThread;
}
Wenn du den Thread zu einem beliebigen Zeitpunkt einfach löscht, kannst du in Teufels küche kommen (in deinem kleinen Beispiel vielleicht nicht, aber wieso sollte mans nicht gleich richtig lernen...). Du solltest dem Thread a) signalisieren dass er sich zu beenden hat, b) warten bis er es getan und damit seine Ressourcen aufgeräumt hat, und c) ihn dann löschen.

Verfasst: 10. September 2009 12:10
von Christian81
Delryn hat geschrieben: Das funktioniert schon korrekt so.
Na wenn Du meinst - viel Spass beim Bug-suchen :)

Und hier noch ein paar Infos für unserem C++-Experten: http://msdn.microsoft.com/en-us/library ... S.80).aspx

Verfasst: 10. September 2009 12:33
von Delryn
Christian81 hat geschrieben:
Delryn hat geschrieben: Das funktioniert schon korrekt so.
Na wenn Du meinst - viel Spass beim Bug-suchen :)

Und hier noch ein paar Infos für unserem C++-Experten: http://msdn.microsoft.com/en-us/library ... S.80).aspx
ich mache es fast so wie pfid es beschrieben hat. Wo ist dein Problem?

Nur das ich mit wait() wirklich so lange warte, bis der Thread sich terminiert hat.

Verfasst: 10. September 2009 12:48
von Christian81
Delryn hat geschrieben: ich mache es fast so wie pfid es beschrieben hat. Wo ist dein Problem?
Das das Beispiel von pfid genausowenig geht. Ist meine oder die Erklärung im msdn so unverständlich ???

Verfasst: 10. September 2009 13:08
von Delryn
Christian81 hat geschrieben:
Delryn hat geschrieben: ich mache es fast so wie pfid es beschrieben hat. Wo ist dein Problem?
Das das Beispiel von pfid genausowenig geht. Ist meine oder die Erklärung im msdn so unverständlich ???

Ja. Aber ich (und ich denke alle anderen auch) wäre dankbar, wenn du es nochmal erläutern würdest.

Imho lösen >90% die Threadgeschichte so wie pfid oder ich.

Verfasst: 10. September 2009 14:08
von pfid
Christian81 hat geschrieben:
Delryn hat geschrieben: ich mache es fast so wie pfid es beschrieben hat. Wo ist dein Problem?
Das das Beispiel von pfid genausowenig geht.
Erklär das mal bitte.

Verfasst: 10. September 2009 14:30
von Christian81
pfid hat geschrieben:
Christian81 hat geschrieben:
Delryn hat geschrieben: ich mache es fast so wie pfid es beschrieben hat. Wo ist dein Problem?
Das das Beispiel von pfid genausowenig geht.
Erklär das mal bitte.
Stimmt - ich habe nicht gesehen wo Du m_abort definierst - steht dort ein 'volatile' ist alles ok. Steht dort keins muss es nicht unbedingt gehen. Siehe meine oberen Kommentare und den msdn-Link.