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. Stop a QThread befor quitting application

Stop a QThread befor quitting application

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 3 Posters 2.6k Views 1 Watching
  • 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.
  • ODБOïO Offline
    ODБOïO Offline
    ODБOï
    wrote on last edited by ODБOï
    #1

    Hi,

    I have toubles stopping a QThread when i quit the application.

    I designed a class ProgramParser that will parse very long text files.

    I have another class ThreadSafeParser that is my interface to use a ProgramParser object in a dedicated QThread through Signal/Slots so my GUI is not blocked during parsers work

    // ThreadSafeParser ctor
       parserThread = new QThread(this);
       parser = new ProgramParser();
       parser->moveToThread(parserThread);
    

    So far, OK. Then I put an instance of ThreadSafeParser as contextProperty to use it from QML.
    And connect QGuiApplication aboutToQuit signal to ThreadsafeParser s safeQuit slot.
    if not, parser will still work even if i quit the app.

    ThreadsafeParser parser;
    engine.rootContext()->setContextProperty("parser",&parser);
    QObject::connect(qApp,&QGuiApplication::aboutToQuit,&parser,&ThreadsafeParser::safeQuit);
    

    this is the content of my safeQuit method

        parserThread->quit();
        parserThread->wait();
    

    and this is my ThreadsafeParser destructor

        ~ThreadsafeParser(){
            parserThread->quit();
            parserThread->wait();
        }
    

    with this method the thread is now stopped but applications will quit with code 1073741845

    I also tryed to call deleteLater instead of my own safeQuit method, in this case work in progress will not even stop.

    Please tell me what i'm doing wrong.

    J.HilkJ 1 Reply Last reply
    0
    • ODБOïO Offline
      ODБOïO Offline
      ODБOï
      wrote on last edited by ODБOï
      #11

      WORKING VERSION

      class ProgramParser : public QObject
      {
          Q_OBJECT
      public:
          /// Ctor
          explicit ProgramParser(QObject *parent = nullptr);
      public slots:
          void openFile(QString filePath,int ind);
          void startParsing();// long task
      };
      
      class ThreadsafeParser : public QObject
      {
          Q_OBJECT
          QThread *parserThread;
          ProgramParser *parser;
      public:
          explicit ThreadsafeParser(QObject *parent = nullptr);
      
          ~ThreadsafeParser(){
              qDebug()<<"QUITTING THE QTHREAD";
             // parserThread->quit();  // not needed 
              parserThread->deleteLater();
          }
      signals:
      void s_parse();
      public slots:
          /// Demande de commancer à parser les fichiers
          void startParsing(){
              emit s_parse();
          }
      
      };
      
      ThreadsafeParser::ThreadsafeParser(QObject *parent) : QObject(parent)
      {
          parserThread = new QThread();// QThread(this);
          parser = new ProgramParser;
          parser->moveToThread(parserThread); 
      
        // QObject::connect(parserThread, &QThread::finished, parser, &QObject::deleteLater);
          ///  forward  SIGNALs
          QObject::connect(this,&ThreadsafeParser::s_parse,parser,&ProgramParser::startParsing);
       
          parserThread->start();
      }
      
      

      //main.cpp

      int main(int argc, char *argv[])
      {
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          QGuiApplication app(argc, argv);
         
          QQmlApplicationEngine engine;
        
          ThreadsafeParser safeParser;
           // no neeed to handle this
           //QObject::connect(qApp,&QGuiApplication::aboutToQuit,&safeParser,&ThreadsafeParser::deleteLater);
      
          engine.rootContext()->setContextProperty("parser",&safeParser);
      
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      
          if (engine.rootObjects().isEmpty())
              return -1;
      
          return app.exec();
      }
      
      

      Output in qt creator when i quit the app :

      Y :  -178.062 // parse result
      X :  65.4623 // parse result
      Y :  -178.09  // parse result
      QUITTING THE QTHREAD  // destructor called... 
      10:54:45: C:/.../JobPlan exited with code 0
      
      1 Reply Last reply
      0
      • ODБOïO ODБOï

        Hi,

        I have toubles stopping a QThread when i quit the application.

        I designed a class ProgramParser that will parse very long text files.

        I have another class ThreadSafeParser that is my interface to use a ProgramParser object in a dedicated QThread through Signal/Slots so my GUI is not blocked during parsers work

        // ThreadSafeParser ctor
           parserThread = new QThread(this);
           parser = new ProgramParser();
           parser->moveToThread(parserThread);
        

        So far, OK. Then I put an instance of ThreadSafeParser as contextProperty to use it from QML.
        And connect QGuiApplication aboutToQuit signal to ThreadsafeParser s safeQuit slot.
        if not, parser will still work even if i quit the app.

        ThreadsafeParser parser;
        engine.rootContext()->setContextProperty("parser",&parser);
        QObject::connect(qApp,&QGuiApplication::aboutToQuit,&parser,&ThreadsafeParser::safeQuit);
        

        this is the content of my safeQuit method

            parserThread->quit();
            parserThread->wait();
        

        and this is my ThreadsafeParser destructor

            ~ThreadsafeParser(){
                parserThread->quit();
                parserThread->wait();
            }
        

        with this method the thread is now stopped but applications will quit with code 1073741845

        I also tryed to call deleteLater instead of my own safeQuit method, in this case work in progress will not even stop.

        Please tell me what i'm doing wrong.

        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #2

        @LeLev hi

        Inside your save quit, set the pointer to a Nullptr and inside your destructor check against a Nullptr before attempting to quit and wait
        I think, that should help


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        1
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #3

          Hi,

          Out of curiosity, why do that from two different places ?

          Unless something goes wrong, the destructor will be called anyway and again unless something wrong, aboutToQuit also, therefore it's a bit redundant.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          ODБOïO 1 Reply Last reply
          0
          • SGaistS SGaist

            Hi,

            Out of curiosity, why do that from two different places ?

            Unless something goes wrong, the destructor will be called anyway and again unless something wrong, aboutToQuit also, therefore it's a bit redundant.

            ODБOïO Offline
            ODБOïO Offline
            ODБOï
            wrote on last edited by
            #4

            @SGaist said in Stop a QThread befor quitting application:

            why do that from two different places

            i do from one or the other
            i first tryed to call only deleteLater

            QObject::connect(qApp,&QGuiApplication::aboutToQuit,&parser,&ThreadsafeParser::deleteLater );
            

            and expected this to be called

            ~ThreadsafeParser(){
                   parserThread->quit();
                   parserThread->wait();
               }
            

            but application is exiting with code 1073741845

            then i have created my safeQuit method

            QObject::connect(qApp,&QGuiApplication::aboutToQuit,&parser,&ThreadsafeParser::safeQuit );
            
            ...
            void safeQuit(){
                    parserThread->quit();
                    parserThread->wait();
                }
            

            in this case parser is still parsing if i quit app.

            tomorrow i will try to set parserThread = nullptr as @J-Hilk suggested

            ~ThreadsafeParser(){
                   parserThread->quit();
                   parserThread->wait();
               
                  parserThread = nullptr
               }
            

            thx for the interest

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #5

              How is that ThreadsafeParser object handled ?

              Because I just realised that you are potentially creating a double delete with your deleteLater call since it seems that parser is an object that's on the stack.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              ODБOïO 2 Replies Last reply
              0
              • SGaistS SGaist

                How is that ThreadsafeParser object handled ?

                Because I just realised that you are potentially creating a double delete with your deleteLater call since it seems that parser is an object that's on the stack.

                ODБOïO Offline
                ODБOïO Offline
                ODБOï
                wrote on last edited by
                #6

                @SGaist said in Stop a QThread befor quitting application:

                How is that ThreadsafeParser object handled ?

                i create one in my main cpp thats all

                ThreadsafeParser parser;
                engine.rootContext()->setContextProperty("parser",&parser);
                QObject::connect(qApp,&QGuiApplication::aboutToQuit,&parser,&ThreadsafeParser::safeQuit);
                
                1 Reply Last reply
                0
                • SGaistS SGaist

                  How is that ThreadsafeParser object handled ?

                  Because I just realised that you are potentially creating a double delete with your deleteLater call since it seems that parser is an object that's on the stack.

                  ODБOïO Offline
                  ODБOïO Offline
                  ODБOï
                  wrote on last edited by
                  #7

                  @SGaist said in Stop a QThread befor quitting application:

                  parser is an object that's on the stack

                  no, it is on heap, in my first post

                  parserThread = new QThread(this);
                     parser = new ProgramParser();
                     parser->moveToThread(parserThread);
                  
                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    Then, no it's on the stack as I was talking about your ThreadsafeParser object which is also called parser (this is way using clear variable names is very important).

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    ODБOïO 1 Reply Last reply
                    1
                    • SGaistS SGaist

                      Then, no it's on the stack as I was talking about your ThreadsafeParser object which is also called parser (this is way using clear variable names is very important).

                      ODБOïO Offline
                      ODБOïO Offline
                      ODБOï
                      wrote on last edited by
                      #9
                      This post is deleted!
                      1 Reply Last reply
                      0
                      • ODБOïO Offline
                        ODБOïO Offline
                        ODБOï
                        wrote on last edited by ODБOï
                        #10

                        Hi,
                        I came back to the official example (i read it long time ago and was able to design multiple multithreaded application since. Now for some reason i'm stuck ): https://doc.qt.io/qt-5/qthread.html#details

                        I do exactly the same thing, My ProgramParser is the Worker of the example.
                        And my ThreadsafeParser is the Controller.

                        then i my main i just connect app's quit signal to deleteLater slot of My 'Controller' aka ThreadsafeParser

                        QObject::connect(qApp,&QGuiApplication::aboutToQuit,&safeParser,&ThreadsafeParser::deleteLater);
                        

                        so this must be called right ?

                        ~ThreadsafeParser(){
                            qDebug()<<"QUITTING THE QTHREAD";
                            parserThread.quit();
                            parserThread.wait();
                        }
                        

                        and since my parserThread 's finished is connected to my ProgramParser (Worker) deleteLater

                        QObject::connect(&parserThread, &QThread::finished, parser, &QObject::deleteLater);
                        

                        I expect this to quit cleanly, but when i quit , the work is still in progress

                        edit

                        i changed the destructor to

                        ~ThreadsafeParser(){
                                 parserThread->deleteLater();
                            }
                        

                        and putted parserThread on heap instead of stack
                        and passed ProgramParser *parser; to member instead of creating it in ThreadsafeParser's ctor

                        now QThread is stopped (it looks like) but application don't quit cleanly, i got : app crashed message.

                        Can this be related to the compiler i use, i did the exact same thing more than 10 times and it worked perfectly with MinGw compilers, for this project i have to use MSVC17 32bit
                        This is the only difference i see

                        1 Reply Last reply
                        0
                        • ODБOïO Offline
                          ODБOïO Offline
                          ODБOï
                          wrote on last edited by ODБOï
                          #11

                          WORKING VERSION

                          class ProgramParser : public QObject
                          {
                              Q_OBJECT
                          public:
                              /// Ctor
                              explicit ProgramParser(QObject *parent = nullptr);
                          public slots:
                              void openFile(QString filePath,int ind);
                              void startParsing();// long task
                          };
                          
                          class ThreadsafeParser : public QObject
                          {
                              Q_OBJECT
                              QThread *parserThread;
                              ProgramParser *parser;
                          public:
                              explicit ThreadsafeParser(QObject *parent = nullptr);
                          
                              ~ThreadsafeParser(){
                                  qDebug()<<"QUITTING THE QTHREAD";
                                 // parserThread->quit();  // not needed 
                                  parserThread->deleteLater();
                              }
                          signals:
                          void s_parse();
                          public slots:
                              /// Demande de commancer à parser les fichiers
                              void startParsing(){
                                  emit s_parse();
                              }
                          
                          };
                          
                          ThreadsafeParser::ThreadsafeParser(QObject *parent) : QObject(parent)
                          {
                              parserThread = new QThread();// QThread(this);
                              parser = new ProgramParser;
                              parser->moveToThread(parserThread); 
                          
                            // QObject::connect(parserThread, &QThread::finished, parser, &QObject::deleteLater);
                              ///  forward  SIGNALs
                              QObject::connect(this,&ThreadsafeParser::s_parse,parser,&ProgramParser::startParsing);
                           
                              parserThread->start();
                          }
                          
                          

                          //main.cpp

                          int main(int argc, char *argv[])
                          {
                              QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                          
                              QGuiApplication app(argc, argv);
                             
                              QQmlApplicationEngine engine;
                            
                              ThreadsafeParser safeParser;
                               // no neeed to handle this
                               //QObject::connect(qApp,&QGuiApplication::aboutToQuit,&safeParser,&ThreadsafeParser::deleteLater);
                          
                              engine.rootContext()->setContextProperty("parser",&safeParser);
                          
                              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                          
                              if (engine.rootObjects().isEmpty())
                                  return -1;
                          
                              return app.exec();
                          }
                          
                          

                          Output in qt creator when i quit the app :

                          Y :  -178.062 // parse result
                          X :  65.4623 // parse result
                          Y :  -178.09  // parse result
                          QUITTING THE QTHREAD  // destructor called... 
                          10:54:45: C:/.../JobPlan exited with code 0
                          
                          1 Reply Last reply
                          0
                          • ODБOïO Offline
                            ODБOïO Offline
                            ODБOï
                            wrote on last edited by ODБOï
                            #12

                            ... I only removed :

                            • my own deletion handling (QObject::connect(qApp,&QGuiApplication::aboutToQuit,&safeParser,&ThreadsafeParser::deleteLater))
                            • the parserThread->quit() line in my destructor
                            • and the this i was passing to parserThread : (parserThread = new QThread(this);)
                              now this works perfectly. Exit with code 0.
                             //QObject::connect(qApp,&QGuiApplication::aboutToQuit,&safeParser,&ThreadsafeParser::deleteLater); // no need
                             // parserThread->quit();  //no need this in the destructor 
                            

                            I will update the la code i pasted.

                            @J-Hilk and @SGaist thank you

                            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