QThread.terminate() Problem unter Linux, Signale löschen

Verschiedenes zu Qt
Antworten
streen
Beiträge: 3
Registriert: 20. November 2008 12:48

QThread.terminate() Problem unter Linux, Signale löschen

Beitrag von streen »

Hallo,

Ich habe folgendes Problem, in meiner GUI habe ich einen QThread erzeugt, der im Hintergrund diverse berechnungen durchführt. Wenn auf der GUI der "Abort" Button gedrückt wird soll dieser Thread abgeschossen werden. Da ich in dem Thread keinerlei Mutexe oder ähnliches verwende geht das ganz gut indem ich einfach: meinThread.terminate() mache. Das ganze klappt unter Windows wunderbar. Da die Software aber auch unter Linux laufen soll habe ich das da natürlich auch getestet und da steigt die Software komplett mit einen Fehler komplett aus (Fatal exception not rethrown). Okay es musste eine andere lösung her, da selbst wenn ich in meinem Thread die Exception weitergebe (mit throw) schmiert es ab (hab da schon diverse sachen probiert, falls jemand eine Idee haben sollte wie ich das doch noch in den Griff bekommen, gerne her damit :-) )

In meinem Thread ist jetzt einfach ein boolsches abbruchkriterium das aus den run() aussteigt, lieder habe ich da bis zu 3 sekunden abbruchzeit, bis dieses Kriterium wieder getestet werden kann. Deshalb habe ich folgende (mMn recht abenteuerliche Konstruktion):

Das ganze Problem ist, wenn ein User mal wieder anstatt einmal auf abort zu klicken, mehrfach drauf hämmert (die Gui sollte möglichst DAU sicher sein, deswegen ist das leider auch ein use case :roll: ), wird das Signal clicked() vom Button trotzdem ausgelößt obwohl es während des blockierenden wait eigendlich disabled ist.
Scheinbar werden alle Singale in einer Art Queue abgelegt, wenn ein blockierender Aufruf in der GUI stattfindet (mStitchThread->wait(); in meinem Fall) und dann abgearbeitet, wenn wieder Zeit ist (in dem Fall wenn die Funktion verlassen wurde). Zu dem Zeitppunkt ist der Button ja wieder enabled... Was zu einem schnellen Wechsel von run/abort führt... wobei der abort wie gesagt wieder 2-3 Sekunden dauert ...
Gibt es irgendeine Möglichkeit am ende des blockes alle bereits ausgelößten signale die in der "Queue" sind zu löschen? Ich dachte eigendlich dass das durch das blocken von den Signalen funktioniert, tut es aber leider nicht.

Ich hoffe mal ich konnte mein Problem einigermaßen verständlich machen.

Danke schon mal im Vorraus, Streen

Code: Alles auswählen

if (mStitchThread->isRunning())
    {
        emit updateStatus("Aborting... please wait.");
        // disable all items
        mParent->setEnabled(false);

        // disconnect the signals
        this->unregisterSignalSlot();
        // block all signals during aborting
        mParent->blockSignals(true); 
        
        // force repaint
        mParent->update();
        mParent->repaint();
        
        // Abort the thread
        mStitchThread->abort(); // abort variable wird hier gesetzt
        mStitchThread->wait();
        
        // re register the signals and slots
        this->registerSignalSlot();
        mParent->setEnabled(true);

        // rename the button
        emit updateStatus("Run has been aborted.");
        mRunButton->setText("Run");

        mParent->blockSignals(false);


    }
    else
    {
        // pass the settings to the Thread
        mStitchThread->setImagePath           (mInputPathLineEdit->text());
        
        // then start the thread
        mStitchThread->start();

        // rename the button
        mRunButton->setText("Abort");
    }
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

meinThread.terminate() mache.
terminate ist assynchron, das heist du schickst dem thread nur ein signal ... und verlaesst die ganze geschichte .... dann ist der thread noch in nem undefinierten Zustand, bis er irgendwann beendet ist. in dieser zeit sollte jeder zugriff auf den thread zu unvorhergesehenen ergebnissen fuehren

um sicherzustellen, das keiner auf dem thread weiter rumhaemmert, waehrend er im beim runterfahren ist, kannst direkt nach dem terminate() nen wait() aufrufen ... das heisst dein gui thread kommt erst zurueck, wenn der thread wirklich beendet ist

vorrausgesetzt die GUI (der gui thread) ist der einzige der mit dem thread kommuniziert, stellst so sicher das kein anderer beim runterfahren deinen Thread was in den weg stellt.

Terminate solltest aber wirklich nur in notfaellen fahren ... erst recht ned durch usereingabe.
besser ist die sache mit den abbruchbedingungen.

Die frage ist ... wenn dein Thread abgebrochen wurde ... was kuemmern dich die 3 sek ??? Die gui wird doch ned blockiert ?
wenn ne Art verwaltung fuer den thread im gui thread hasst, kannst den doch vorher rausnehmen ....
wenn der user mit beenden rausgeht, kannst ihm doch die fenster schliessen, und nur die app warten lassen bis alle threads weg sind. intressiert doch den user dann nur 2.trangig, ob der Prozess noch bissi nachlaeuft ....

wenn der user abbrechen drueckt, in nur 1 sek wieder start ... kriegt er entweder nen fehler um die ohren ^^ oder du startest nen wirklich neuen thread ...
Eigentlich solltest dein Programm so aufbauen, das es dir schnurz egal ist, wenn der thread sich genau beendet ... das ist ja einer der Vorteile von multithreading ...

Ciao ...
Antworten