Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QThread does not quit, why?

QThread does not quit, why?

Scheduled Pinned Locked Moved Solved General and Desktop
qthreadquit
8 Posts 4 Posters 3.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    robro
    wrote on last edited by
    #1

    Hi,

    I am using a QThread and it works fine besides that it does not quit.

        QThread myThread;
        QObject::connect(&app, &QApplication::aboutToQuit, myCtrl, &Control::deleteLater);
        QObject::connect(myCtrl, &Control::finished,  &myThread, &QThread::quit);
        QObject::connect(&myThread, &QThread::finished,  &myThread, &QThread::deleteLater);
        myCtrl->moveToThread(&myThread);
        myThread.start();
    
        //Debug:
        QSignalSpy spy(myCtrl, &Control::finished);  //Count was checked later and signal was emitted correct.
    

    The quit process I start with the "QApplication::aboutToQuit()"-signal. This calls the destructor of my class which looks like this:

    Control::~Control()
    {
        qDebug() << "ControlDTOR called!";
        emit finished();
    }
    

    I see that the destructor was called and also the finished signal was emitted.
    However, "myThread.wait()" never returns.

    What could be the reason for this and how can I make it quit in a proper way?

    Thanks!

    1 Reply Last reply
    0
    • kshegunovK Offline
      kshegunovK Offline
      kshegunov
      Moderators
      wrote on last edited by kshegunov
      #2

      Please show us the whole piece of code. You're probably blocking the event loop ... edit: or your thread just goes out of scope ...

      Read and abide by the Qt Code of Conduct

      1 Reply Last reply
      2
      • R Offline
        R Offline
        robro
        wrote on last edited by
        #3

        Thanks,

        I now made a MWE:

        main.cpp:

        #include <QApplication>
        #include <QQmlApplicationEngine>
        #include <QQmlContext>
        #include <QThread>
        #include <control.h>
        
        //Debug:
        #include <QDebug>
        
        int main(int argc, char *argv[])
        {
            QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
            QApplication app(argc, argv);
        
            QApplication::setOrganizationName("a");
            QApplication::setOrganizationDomain("b");
            QApplication::setApplicationName("c");
        
            Control* myControl = new Control();
        
            QThread myThread;
            QObject::connect(&app, &QApplication::aboutToQuit, myControl, &Control::deleteLater);
            QObject::connect(myControl, &Control::finished,  &myThread, &QThread::quit);
            QObject::connect(&myThread, &QThread::finished,  &myThread, &QThread::deleteLater);
            myControl->moveToThread(&myThread);
            myThread.start();
        
            QQmlApplicationEngine engine;
        
            const QUrl url(QStringLiteral("qrc:/main.qml"));
            QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                             &app, [url](QObject *obj, const QUrl &objUrl) {
                if (!obj && url == objUrl)
                    QCoreApplication::exit(-1);
            }, Qt::QueuedConnection);
            engine.load(url);
        
        
            int exitCode = app.exec();
        
            qDebug() << "Started Waiting:";
            myThread.wait(); // Wait for thread to quit
        
            qDebug() << "Quit"; // This is never reached as myThread.wait() blocks forever.
        
        
            return exitCode;
        }
        

        control.h:

        #ifndef CONTROL_H
        #define CONTROL_H
        
        #include <QObject>
        #include <QDebug>
        
        class Control : public QObject
        {
            Q_OBJECT
        public:
            explicit Control(QObject *parent = nullptr);
            ~Control();
        
        signals:
             void finished();
        
        };
        
        #endif // CONTROL_H
        

        control.cpp:

        #include "control.h"
        
        Control::Control(QObject *parent) : QObject(parent)
        {
        
        }
        
        Control::~Control()
        {
            qDebug() << "Control DTOR called!";
            emit finished();
        }
        
        

        Output after closing the QML window:

        Started Waiting:
        Control DTOR called!
        
        1 Reply Last reply
        0
        • Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @robro said in QThread does not quit, why?:

          QObject::connect(&myThread, &QThread::finished, &myThread, &QThread::deleteLater);

          This will crash since your thread is on the stack.

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          1 Reply Last reply
          2
          • R Offline
            R Offline
            robro
            wrote on last edited by
            #5

            Hi,

            I understand.
            I tried the following, but the thread does still not end:

                QThread *myThread = new QThread();
                QObject::connect(myControl, &Control::finished,  myThread, &QThread::quit);
                QObject::connect(myThread, &QThread::finished,  myThread, &QThread::deleteLater);
            

            What is the problem?

            B 1 Reply Last reply
            0
            • R robro

              Hi,

              I understand.
              I tried the following, but the thread does still not end:

                  QThread *myThread = new QThread();
                  QObject::connect(myControl, &Control::finished,  myThread, &QThread::quit);
                  QObject::connect(myThread, &QThread::finished,  myThread, &QThread::deleteLater);
              

              What is the problem?

              B Offline
              B Offline
              Bonnie
              wrote on last edited by Bonnie
              #6

              @robro The solution is

              QObject::connect(myControl, &Control::finished,  myThread, &QThread::quit, Qt::DirectConnection);
              

              The reason is, when the Control::finished signal is emitted, the myControl object lives in the new thread, but the myThread object lives in the main thread, even though it is a thread object.
              (EDITED)
              So when you use the default connection type (Qt::AutoConnection), and the receiver does not live in the thread that emits the signal, Qt::QueuedConnection will be used.
              That means(from the doc):

              The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

              But when your signal is emitted, the application is about to quit the main event loop, aka, the event loop of the receiver's thread. So the slot will never be invoked.

              kshegunovK 1 Reply Last reply
              2
              • R Offline
                R Offline
                robro
                wrote on last edited by
                #7

                Thank you very much for the solution and great explanation!

                1 Reply Last reply
                0
                • B Bonnie

                  @robro The solution is

                  QObject::connect(myControl, &Control::finished,  myThread, &QThread::quit, Qt::DirectConnection);
                  

                  The reason is, when the Control::finished signal is emitted, the myControl object lives in the new thread, but the myThread object lives in the main thread, even though it is a thread object.
                  (EDITED)
                  So when you use the default connection type (Qt::AutoConnection), and the receiver does not live in the thread that emits the signal, Qt::QueuedConnection will be used.
                  That means(from the doc):

                  The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

                  But when your signal is emitted, the application is about to quit the main event loop, aka, the event loop of the receiver's thread. So the slot will never be invoked.

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by kshegunov
                  #8

                  @Bonnie said in QThread does not quit, why?:

                  The solution is

                  
                  QObject::connect(myControl, &Control::finished,  myThread, &QThread::quit, Qt::DirectConnection);
                  
                  

                  And where does it say that this slot is thread-safe?

                  @robro
                  Just quit the thread before you exit the application.

                  QObject::connect(&app, &QApplication::aboutToQuit, myCtrl, &Control::deleteLater);
                  QObject::connect(myCtrl, &Control::finished,  &myThread, &QThread::quit);
                  QObject::connect(&myThread, &QThread::finished, myCtrl, &Control::deleteLater); //< This is needed
                  

                  Which translates simply to:

                  qDebug() << "Started Waiting:";
                  myThread.quit();
                  myThread.wait(); // Wait for thread to quit
                  qDebug() << "Quit";
                  

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  1

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved