[Qt] Sauber Programm beenden wenn QThread noch läuft



  • Hallo,

    Also bisher habe ich eine join() Funktion in meiner abgeleiteten QThread Klasse implementiert, die ich im Destruktor des Hauptfensters aufrufe, wenn der Thread noch läuft:

        void join(){
            if(isRunning()){
                do{
                    QApplication::processEvents();
                } while(!wait(0));
            }
        }
    

    Irgendwann im Desktruktor meines Hauptfensters:

        ~table_widget(){
            if(file_reader && file_reader->isRunning()){
                file_reader->stop();
                file_reader->join();
            }
        }
    

    Mit der stop() Methode wird lediglich ein Boolean cancel = true; gemacht und die Schleife innerhalb des Threads wird in aller Kürze abgebrochen. Dauert nicht lange.

    Und alles funktioniert einwandfrei.

    Aber ist das der richtige Weg das zu tun? Ich hätte kein Problem damit terminate() aufzurufen aber manchmal bleibt das Programm hängen oder gibt Segfaults und das finde ich unschön.

    Irgendwelche Ideen? Oder auch gut so?



  • Es gibt QThread::wait, brauchst das join nicht selber implementieren. processEvents kann auch öfter zu Problemen führen.



  • Generell ist das Standard, wie man mit threads umgehen sollte:

    Thread benachrichtigen, das er aufhören kann/soll
    mit join auf das auslaufen des threads warten ...

    theorethisch könntest nach dem stop noch nen 2. thread / timer aufziehen, der das stoppen des anderen threads überwacht .... und nach einem timeout ein kill schickt.
    Aber eigentlich zeigt es , das dein eigentlicher Arbeitsthread dann ein problem hat und beim stoppen aufn lock läuft oder so.

    Das Blöde ist eigentlich nur das stoppen des Threads an sich .... eigentlich "ists doof" ständig schauen zu muessen, ob man weitermachen darf oder nicht ... aber wenn dein Thread nie in ein unterbrechbaren zustand geht, kannst ihn nur von extern killen.
    Mit filesystem io hättest da aber generell glück, das sind meist unterbrechbare zustände ...
    Generell könntest also auch dem thread ein signal schicken, und im Signalhändler dinge tun, die das Lesen unterbinden (fileflags setzen etc)
    Aber wenn soweiso schon ständig rausfällst aus deiner operation, kannst natürlich auch ne variable abfragen, ob weitermachen darfst oder nicht. dein cancel ist geschützt oder ein atomic ?

    Eine andere Frage ist auch, was dein FileReader hauptsächlichst macht:
    ist das Lesen Trivial und die verrarbeitung der Daten die Hauptlast -> Threads
    ist das Lesen an sich die Hauptlast und die Daten werden sowieso in einem anderen Thread (MainThread) verarbeitet -> sollte man vielleicht asio in betracht ziehen

    Ciao ...



  • @Mechanics sagte in [Qt] Sauber Programm beenden wenn QThread noch läuft:

    Es gibt QThread::wait, brauchst das join nicht selber implementieren. processEvents kann auch öfter zu Problemen führen.

    Das QThread::wait() scheint aber den Destruktor zu blockieren. Hier folgende Methode die ich im Desktruktor des Main Threads aufrufe, damit alles sauber runterfährt:

        ~table_widget(){
            cancel_file_reader();
        }
    
        void cancel_file_reader(){
            if(file_reader && file_reader->isRunning()){
                file_reader->stop();
    
                do{
                    QApplication::processEvents();
                } while(!file_reader->wait(0));
            }
        }
    

    Das funktioniert sehr gut! Der Thread arbeitet in einer Schleife, wo while(!cancel && ...) { ... }, die Methode stop() setzt das Boolean cancel auf true. Der Thread kann somit direkt unterbrochen werden, denn jeder Schleifendurchlauf im Thread kostet mich nur einige Millisekunden. Ohne dieses QApplication::processEvents() scheint der Thread jedoch nie zum Ende zu gelangen. Mit QThread::wait(0) kuck ich dann so lange, bis der Thread ans Ende gelangt.

    Würde ich also im Main Thread einfach nur folgendes schreiben:

        void cancel_file_reader(){
            if(file_reader && file_reader->isRunning()){
                file_reader->stop();
                while(!file_reader->wait(100));
            }
        }
    

    Dann wird das Programm nie beendet.


Anmelden zum Antworten