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. terminating a thread
Forum Updated to NodeBB v4.3 + New Features

terminating a thread

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 3 Posters 2.3k Views 3 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.
  • M Offline
    M Offline
    mzimmers
    wrote on 26 Apr 2018, 18:49 last edited by
    #1

    Hi, all -

    I've got a small application with a worker thread that runs in a loop. I'd like to terminate the worker thread (and stop the application) when the user pushes a quit button.

    Here's what I've got so far:

    class Worker : public QThread
    {...}
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget widget;
        Worker worker;
    
        QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::quit);
    

    But I now see that the quit() call only affects an event loop within a thread, not the actual thread itself.

    So, how do I properly shut down the thread before exiting the application?

    Thanks...

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 26 Apr 2018, 19:31 last edited by
      #2

      Hi,

      Do you mean you have in infinite loop in the run of your thread ?

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

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mzimmers
        wrote on 26 Apr 2018, 19:32 last edited by
        #3

        Yes...it reads from a socket, and when it gets something, passes it to the display widget.

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 26 Apr 2018, 19:36 last edited by
          #4

          In that case, make the loop stoppable:

          void MyThread::stop()
          {
              continue.deref();
          }
          void MyThread::run() 
          {
             continue.ref();
              while(continue) {
                  /// Do your stuff
              }
          }
          

          continue being a QAtomicInt.

          You can then call stop in your application, then QThread::wait() to ensure its finished before continuing.

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

          1 Reply Last reply
          4
          • M Offline
            M Offline
            mzimmers
            wrote on 26 Apr 2018, 19:41 last edited by
            #5

            Interesting. So, MyThread::stop would be a slot to receive the signal from the display widget? Would MyThread::run then send a signal to the QApplication prior to exiting? And if so, is there concern for a race condition under which the Application might try to exit before the thread has terminated?

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 26 Apr 2018, 19:44 last edited by
              #6

              No there's no signal emitted since you implement your own version of run. Note that you can send a signal yourself if you need/want to. The call to wait after the call to stop is where you ensure that your thread stops before you continue with your application.

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

              M 1 Reply Last reply 26 Apr 2018, 19:59
              1
              • S SGaist
                26 Apr 2018, 19:44

                No there's no signal emitted since you implement your own version of run. Note that you can send a signal yourself if you need/want to. The call to wait after the call to stop is where you ensure that your thread stops before you continue with your application.

                M Offline
                M Offline
                mzimmers
                wrote on 26 Apr 2018, 19:59 last edited by
                #7

                @SGaist OK, I understand the mechanics of the worker thread, but how to invoke the wait is a bit of a mystery. Here's my main:

                int main(int argc, char *argv[])
                {
                    QApplication a(argc, argv);
                    Widget widget;
                    Worker worker;
                
                    QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText);
                    QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit);
                
                    widget.show();
                    worker.start();
                    return a.exec();
                }
                

                I don't see:

                • where to put the wait(), given that a.exec() runs infinitely.
                • how to terminate the application (worker::run() could send a signal after it exits its loop, I suppose).
                K 1 Reply Last reply 26 Apr 2018, 20:21
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 26 Apr 2018, 20:07 last edited by
                  #8

                  You could use a lambda that calls doQuit and then wait rather than than connecting doQuit directly. Or you can integrate wait in doQuit.

                  Add a signal to your Worker class that you emit at the end of the loop.

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

                  M 1 Reply Last reply 26 Apr 2018, 20:25
                  0
                  • M mzimmers
                    26 Apr 2018, 19:59

                    @SGaist OK, I understand the mechanics of the worker thread, but how to invoke the wait is a bit of a mystery. Here's my main:

                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        Widget widget;
                        Worker worker;
                    
                        QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText);
                        QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit);
                    
                        widget.show();
                        worker.start();
                        return a.exec();
                    }
                    

                    I don't see:

                    • where to put the wait(), given that a.exec() runs infinitely.
                    • how to terminate the application (worker::run() could send a signal after it exits its loop, I suppose).
                    K Offline
                    K Offline
                    kshegunov
                    Moderators
                    wrote on 26 Apr 2018, 20:21 last edited by kshegunov
                    #9

                    @mzimmers said in terminating a thread:

                    int main(int argc, char *argv[])
                    {
                        QApplication a(argc, argv);
                        Widget widget;
                        Worker worker;
                    
                        QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText);
                    
                        // Invoke directly as there's no running event loop to process the slot
                        QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit, Qt::DirectConnection);
                        // Connect the aboutToQuit from the `QCoreApplication` so you don't hang when the button's not pressed
                        QObject::connect(&a, &QCoreApplication::aboutToQuit, &worker, &Worker::doQuit, Qt::DirectConnection);
                    
                       widget.show();
                       worker.start();
                    
                        // Store the return value and then wait for the thread to exit
                        int retValue = QApplication::exec();
                        worker.wait();
                        // After the thread has finished, return from main()
                        return retValue;
                    }
                    

                    This is all assuming doQuit is what @SGaist wrote - raising an atomic flag to tell the thread to quit.

                    Btw, you can use QThread::requestInterruption and QThread::isInterruptionRequested instead of rolling your own.

                    Read and abide by the Qt Code of Conduct

                    M 1 Reply Last reply 26 Apr 2018, 20:28
                    4
                    • S SGaist
                      26 Apr 2018, 20:07

                      You could use a lambda that calls doQuit and then wait rather than than connecting doQuit directly. Or you can integrate wait in doQuit.

                      Add a signal to your Worker class that you emit at the end of the loop.

                      M Offline
                      M Offline
                      mzimmers
                      wrote on 26 Apr 2018, 20:25 last edited by
                      #10

                      @SGaist so my worker thread will signal the QApplication, so that the QApplication can quit. Correct?

                      I'm still lost regarding the use of wait(). It can't reside in the worker object, as a thread can't wait for itself. And I have no context from which to use it in main(). Do I need a parent class/object for my worker?

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 26 Apr 2018, 20:28 last edited by
                        #11

                        See @kshegunov's excellent alternative.

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

                        1 Reply Last reply
                        1
                        • K kshegunov
                          26 Apr 2018, 20:21

                          @mzimmers said in terminating a thread:

                          int main(int argc, char *argv[])
                          {
                              QApplication a(argc, argv);
                              Widget widget;
                              Worker worker;
                          
                              QObject::connect(&worker, &Worker::newResponseText, &widget, &Widget::addText);
                          
                              // Invoke directly as there's no running event loop to process the slot
                              QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit, Qt::DirectConnection);
                              // Connect the aboutToQuit from the `QCoreApplication` so you don't hang when the button's not pressed
                              QObject::connect(&a, &QCoreApplication::aboutToQuit, &worker, &Worker::doQuit, Qt::DirectConnection);
                          
                             widget.show();
                             worker.start();
                          
                              // Store the return value and then wait for the thread to exit
                              int retValue = QApplication::exec();
                              worker.wait();
                              // After the thread has finished, return from main()
                              return retValue;
                          }
                          

                          This is all assuming doQuit is what @SGaist wrote - raising an atomic flag to tell the thread to quit.

                          Btw, you can use QThread::requestInterruption and QThread::isInterruptionRequested instead of rolling your own.

                          M Offline
                          M Offline
                          mzimmers
                          wrote on 26 Apr 2018, 20:28 last edited by
                          #12

                          @kshegunov so, do I correctly understand that, in your example, the QApplication will terminate before the worker thread?

                          I didn't know you could do that...

                          K 1 Reply Last reply 26 Apr 2018, 20:30
                          0
                          • M mzimmers
                            26 Apr 2018, 20:28

                            @kshegunov so, do I correctly understand that, in your example, the QApplication will terminate before the worker thread?

                            I didn't know you could do that...

                            K Offline
                            K Offline
                            kshegunov
                            Moderators
                            wrote on 26 Apr 2018, 20:30 last edited by kshegunov
                            #13

                            You can exit the (main) event loop at any time you want, you need to wait before returning from main() so your process doesn't terminate before the thread has done so. So yes, you can exit the loop before returning from main(). :)

                            PS.
                            QCoreApplication::exec does practically nothing, it's a convenience function, you can substitute it with:

                            QEventLoop loop;
                            return loop.exec();
                            

                            Read and abide by the Qt Code of Conduct

                            M 1 Reply Last reply 26 Apr 2018, 20:34
                            3
                            • K kshegunov
                              26 Apr 2018, 20:30

                              You can exit the (main) event loop at any time you want, you need to wait before returning from main() so your process doesn't terminate before the thread has done so. So yes, you can exit the loop before returning from main(). :)

                              PS.
                              QCoreApplication::exec does practically nothing, it's a convenience function, you can substitute it with:

                              QEventLoop loop;
                              return loop.exec();
                              
                              M Offline
                              M Offline
                              mzimmers
                              wrote on 26 Apr 2018, 20:34 last edited by
                              #14

                              @kshegunov well, isn't that something. Very nice.

                              I implemented it a bit differently from your example:

                              int main(int argc, char *argv[])
                              {
                                  QApplication a(argc, argv);
                                  Widget widget;
                                  Worker worker;
                                  int rc;
                              
                                  QObject::connect(&worker, &Worker::newResponse, &widget, &Widget::addText);
                                  QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit);
                                  QObject::connect(&worker, &Worker::reachedEndOfThread, &a, &QApplication::exit);
                              
                                  widget.show();
                                  worker.start();
                                  rc = a.exec();
                                  worker.wait();
                                  return rc;
                              }
                              
                              Seems to work fine. Thanks, guys.
                              
                              K 1 Reply Last reply 26 Apr 2018, 20:37
                              0
                              • M mzimmers
                                26 Apr 2018, 20:34

                                @kshegunov well, isn't that something. Very nice.

                                I implemented it a bit differently from your example:

                                int main(int argc, char *argv[])
                                {
                                    QApplication a(argc, argv);
                                    Widget widget;
                                    Worker worker;
                                    int rc;
                                
                                    QObject::connect(&worker, &Worker::newResponse, &widget, &Widget::addText);
                                    QObject::connect(&widget, &Widget::quitButtonPushed, &worker, &Worker::doQuit);
                                    QObject::connect(&worker, &Worker::reachedEndOfThread, &a, &QApplication::exit);
                                
                                    widget.show();
                                    worker.start();
                                    rc = a.exec();
                                    worker.wait();
                                    return rc;
                                }
                                
                                Seems to work fine. Thanks, guys.
                                
                                K Offline
                                K Offline
                                kshegunov
                                Moderators
                                wrote on 26 Apr 2018, 20:37 last edited by
                                #15

                                You should still connect the aboutToQuit signal, as you may click the x in the top right of the window, which wouldn't trigger your doQuit.

                                Read and abide by the Qt Code of Conduct

                                1 Reply Last reply
                                2
                                • M Offline
                                  M Offline
                                  mzimmers
                                  wrote on 26 Apr 2018, 20:39 last edited by
                                  #16

                                  Done. Thanks again.

                                  1 Reply Last reply
                                  1

                                  1/16

                                  26 Apr 2018, 18:49

                                  • Login

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