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. How to stop QThread?
Forum Updated to NodeBB v4.3 + New Features

How to stop QThread?

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 4 Posters 4.0k 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.
  • Q Offline
    Q Offline
    qwe3
    wrote on last edited by
    #1

    Hi,
    I have application with 2 threads ( main and one for long calculations ). Codes:

    Thread with long calculations:

    Worker::Worker(QObject *parent): QObject(parent)
    {
    }
    
    void Worker::calculate()
    {
        for(int i=0; i<10000000;i++)
        {
            QCoreApplication::processEvents();
            ...
        }
    
        emit endCalc();
    }
    

    Main thread ( in one method ):

        QThread thread(this);
        Worker worker;
        worker.moveToThread(&thread);
    
        QObject::connect(&worker, &Worker::endCalc, this, &MainWindow::someSlot);
        QObject::connect(this, &MainWindow::startCal, &worker, &Worker::calculate);
    
        thread.start();
    
        QEventLoop q;
    
        connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
    
        emit startCal();
    
        q.exec();
    
        thread.quit();
        thread.wait();
    

    And the problem is that, when I close application when there are still calculations in the second thread ( Worker ), in the main thread I wait in the line thread.wait(); and my app still running ( gui is closed, but there is still running ).

    jsulmJ J.HilkJ KroMignonK 3 Replies Last reply
    0
    • Q qwe3

      Hi,
      I have application with 2 threads ( main and one for long calculations ). Codes:

      Thread with long calculations:

      Worker::Worker(QObject *parent): QObject(parent)
      {
      }
      
      void Worker::calculate()
      {
          for(int i=0; i<10000000;i++)
          {
              QCoreApplication::processEvents();
              ...
          }
      
          emit endCalc();
      }
      

      Main thread ( in one method ):

          QThread thread(this);
          Worker worker;
          worker.moveToThread(&thread);
      
          QObject::connect(&worker, &Worker::endCalc, this, &MainWindow::someSlot);
          QObject::connect(this, &MainWindow::startCal, &worker, &Worker::calculate);
      
          thread.start();
      
          QEventLoop q;
      
          connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
      
          emit startCal();
      
          q.exec();
      
          thread.quit();
          thread.wait();
      

      And the problem is that, when I close application when there are still calculations in the second thread ( Worker ), in the main thread I wait in the line thread.wait(); and my app still running ( gui is closed, but there is still running ).

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @qwe3 See https://doc.qt.io/qt-5/qthread.html#requestInterruption and https://doc.qt.io/qt-5/qthread.html#isInterruptionRequested

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • Q Offline
        Q Offline
        qwe3
        wrote on last edited by
        #3

        @jsulm Thank you. This looks very good. But I have a question:

        In docs I can read:
        That request is advisory and it is up to code running on the thread to decide if and how it should act upon such request.

        So what if thread don't accept request?

        jsulmJ 1 Reply Last reply
        0
        • Q qwe3

          Hi,
          I have application with 2 threads ( main and one for long calculations ). Codes:

          Thread with long calculations:

          Worker::Worker(QObject *parent): QObject(parent)
          {
          }
          
          void Worker::calculate()
          {
              for(int i=0; i<10000000;i++)
              {
                  QCoreApplication::processEvents();
                  ...
              }
          
              emit endCalc();
          }
          

          Main thread ( in one method ):

              QThread thread(this);
              Worker worker;
              worker.moveToThread(&thread);
          
              QObject::connect(&worker, &Worker::endCalc, this, &MainWindow::someSlot);
              QObject::connect(this, &MainWindow::startCal, &worker, &Worker::calculate);
          
              thread.start();
          
              QEventLoop q;
          
              connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
          
              emit startCal();
          
              q.exec();
          
              thread.quit();
              thread.wait();
          

          And the problem is that, when I close application when there are still calculations in the second thread ( Worker ), in the main thread I wait in the line thread.wait(); and my app still running ( gui is closed, but there is still running ).

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

          @qwe3
          processEvent calls, QThread and QEventLoop all in the same scope.....

          Please reconsider your design choices.


          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
          0
          • Q Offline
            Q Offline
            qwe3
            wrote on last edited by
            #5

            @J-Hilk I don't understand. I don't want to freeze GUI, so I decided to create the second thread. I need to change asynchronous code to synchronous, so I find solution here:

            https://doc.qt.io/archives/qq/qq27-responsive-guis.html ( Waiting in a Local Event Loop )

            jsulmJ 1 Reply Last reply
            0
            • Q qwe3

              @jsulm Thank you. This looks very good. But I have a question:

              In docs I can read:
              That request is advisory and it is up to code running on the thread to decide if and how it should act upon such request.

              So what if thread don't accept request?

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @qwe3 said in How to stop QThread?:

              So what if thread don't accept request?

              Then it does not terminate.
              But sinse it's your thread you can do it the right way, right?
              If you don't want to do it right you can still kill your thread using https://doc.qt.io/qt-5/qthread.html#terminate

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • Q qwe3

                @J-Hilk I don't understand. I don't want to freeze GUI, so I decided to create the second thread. I need to change asynchronous code to synchronous, so I find solution here:

                https://doc.qt.io/archives/qq/qq27-responsive-guis.html ( Waiting in a Local Event Loop )

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @qwe3 said in How to stop QThread?:

                . I don't want to freeze GUI

                But you do: q.exec();
                So, you're waiting in your main thread for the other thread to terminate...

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • Q Offline
                  Q Offline
                  qwe3
                  wrote on last edited by qwe3
                  #8

                  @jsulm When I do: q.exec() I wait in this line in the code, but GUI is not freezed ( I see hovers etc ). I need these calculations in these function ( in main thread ).

                  jsulmJ 1 Reply Last reply
                  0
                  • Q qwe3

                    @jsulm When I do: q.exec() I wait in this line in the code, but GUI is not freezed ( I see hovers etc ). I need these calculations in these function ( in main thread ).

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @qwe3 Yes, you're correct. You do not block the UI as you have a local event loop.
                    Do you really have to make this synchronous?

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • Q qwe3

                      Hi,
                      I have application with 2 threads ( main and one for long calculations ). Codes:

                      Thread with long calculations:

                      Worker::Worker(QObject *parent): QObject(parent)
                      {
                      }
                      
                      void Worker::calculate()
                      {
                          for(int i=0; i<10000000;i++)
                          {
                              QCoreApplication::processEvents();
                              ...
                          }
                      
                          emit endCalc();
                      }
                      

                      Main thread ( in one method ):

                          QThread thread(this);
                          Worker worker;
                          worker.moveToThread(&thread);
                      
                          QObject::connect(&worker, &Worker::endCalc, this, &MainWindow::someSlot);
                          QObject::connect(this, &MainWindow::startCal, &worker, &Worker::calculate);
                      
                          thread.start();
                      
                          QEventLoop q;
                      
                          connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
                      
                          emit startCal();
                      
                          q.exec();
                      
                          thread.quit();
                          thread.wait();
                      

                      And the problem is that, when I close application when there are still calculations in the second thread ( Worker ), in the main thread I wait in the line thread.wait(); and my app still running ( gui is closed, but there is still running ).

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by
                      #10

                      @qwe3 said in How to stop QThread?:

                      And the problem is that, when I close application when there are still calculations in the second thread ( Worker ), in the main thread I wait in the line thread.wait(); and my app still running ( gui is closed, but there is still running ).

                      Your design looks to me very complicate for such a "trivial" use case.
                      Why you are not using QtConcurrent::run()?
                      In addition with QFuturWatcher you could be informed about calculation end and got result.

                      Take a look at https://doc.qt.io/qt-5/qtconcurrentrun.html.

                      Or did I miss something?

                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                      1 Reply Last reply
                      0
                      • Q Offline
                        Q Offline
                        qwe3
                        wrote on last edited by
                        #11

                        @KroMignon But can I send signals from the second thread ( long operations ) like current progress? I never used QtConcurrent.

                        @jsulm Yes, I have to. I changed code and ... it doesn't work. Now it looks like this:

                        Worker::Worker(QObject *parent): QObject(parent)
                        {
                        }
                        
                        void Worker::calculate()
                        {
                            for(int i=0; i<10000000;i++)
                            {
                                QCoreApplication::processEvents();
                                if( QThread::currentThread()->isInterruptionRequested())
                                {
                                            qDebug()<<"return";
                                            return;
                                }    
                                ...
                            }
                        
                            emit endCalc();
                        }
                        

                        And in main thread ( thread is now a pointer ):

                            thread->start();
                        
                            QEventLoop q;
                        
                            connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
                        
                            emit startCal();
                        
                            q.exec();
                        
                            thread->requestInterruption();
                            thread->quit();
                            thread->wait();
                        

                        When I close the app using X button, I see on debuq "return", but application is still wait on thread->wait();

                        jsulmJ KroMignonK 2 Replies Last reply
                        0
                        • Q qwe3

                          @KroMignon But can I send signals from the second thread ( long operations ) like current progress? I never used QtConcurrent.

                          @jsulm Yes, I have to. I changed code and ... it doesn't work. Now it looks like this:

                          Worker::Worker(QObject *parent): QObject(parent)
                          {
                          }
                          
                          void Worker::calculate()
                          {
                              for(int i=0; i<10000000;i++)
                              {
                                  QCoreApplication::processEvents();
                                  if( QThread::currentThread()->isInterruptionRequested())
                                  {
                                              qDebug()<<"return";
                                              return;
                                  }    
                                  ...
                              }
                          
                              emit endCalc();
                          }
                          

                          And in main thread ( thread is now a pointer ):

                              thread->start();
                          
                              QEventLoop q;
                          
                              connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
                          
                              emit startCal();
                          
                              q.exec();
                          
                              thread->requestInterruption();
                              thread->quit();
                              thread->wait();
                          

                          When I close the app using X button, I see on debuq "return", but application is still wait on thread->wait();

                          jsulmJ Offline
                          jsulmJ Offline
                          jsulm
                          Lifetime Qt Champion
                          wrote on last edited by jsulm
                          #12

                          @qwe3 said in How to stop QThread?:

                          connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);

                          emit startCal();
                          
                          q.exec();
                          
                          thread->requestInterruption();
                          

                          Are you aware that requestInterruption() will be send to thread after it finished? Because q.exec() blocks until endCalc is emitted. What is the point of doing so?

                          Also, you should either emit this endCalc also when termination is requested or use https://doc.qt.io/qt-5/qthread.html#finished signal to terminate the local event loop.

                          https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • Q Offline
                            Q Offline
                            qwe3
                            wrote on last edited by
                            #13

                            @jsulm When I close app and there are still operations in second thread I don't emit endCalc, but q.exec() is done.

                            jsulmJ 1 Reply Last reply
                            0
                            • Q qwe3

                              @jsulm When I close app and there are still operations in second thread I don't emit endCalc, but q.exec() is done.

                              jsulmJ Offline
                              jsulmJ Offline
                              jsulm
                              Lifetime Qt Champion
                              wrote on last edited by
                              #14

                              @qwe3 said in How to stop QThread?:

                              but q.exec() is done

                              How can it be done and how did you verify it is done? The only condition in your code to terminate the local event loop is endCalc signal...

                              https://forum.qt.io/topic/113070/qt-code-of-conduct

                              1 Reply Last reply
                              0
                              • Q Offline
                                Q Offline
                                qwe3
                                wrote on last edited by qwe3
                                #15

                                @jsulm I debuq informations like this:

                                second thread:

                                void Worker::calculate()
                                {
                                    for(int i=0; i<10000000;i++)
                                    {
                                        QCoreApplication::processEvents();
                                        if( QThread::currentThread()->isInterruptionRequested())
                                        {
                                                    qDebug()<<"return";
                                                    return;
                                        }    
                                        ...
                                    }
                                
                                    qDebug()<<"before emit endCalc";
                                    emit endCalc();
                                }
                                

                                In main thread:

                                    q.exec();
                                
                                   qDebug()<<"after exec";
                                   thread->requestInterruption();
                                   qDebug()<<"after requestInterruption";
                                   thread->quit();
                                   qDebug()<<"after quit";
                                   thread->wait();
                                

                                When I close application I see on debuq:

                                after exec
                                after requestInterruption
                                after quit
                                return
                                

                                But it is still waiting on thread->wait();

                                So I don't emit endCalc(), but Local Event Loop is done ( of course this event loop is the second event loop in my app - the first one is in main.cpp and this one ( the second one ) is in my own class method ).

                                1 Reply Last reply
                                0
                                • Q qwe3

                                  @KroMignon But can I send signals from the second thread ( long operations ) like current progress? I never used QtConcurrent.

                                  @jsulm Yes, I have to. I changed code and ... it doesn't work. Now it looks like this:

                                  Worker::Worker(QObject *parent): QObject(parent)
                                  {
                                  }
                                  
                                  void Worker::calculate()
                                  {
                                      for(int i=0; i<10000000;i++)
                                      {
                                          QCoreApplication::processEvents();
                                          if( QThread::currentThread()->isInterruptionRequested())
                                          {
                                                      qDebug()<<"return";
                                                      return;
                                          }    
                                          ...
                                      }
                                  
                                      emit endCalc();
                                  }
                                  

                                  And in main thread ( thread is now a pointer ):

                                      thread->start();
                                  
                                      QEventLoop q;
                                  
                                      connect(&worker, &Worker::endCalc, &q, &QEventLoop::quit);
                                  
                                      emit startCal();
                                  
                                      q.exec();
                                  
                                      thread->requestInterruption();
                                      thread->quit();
                                      thread->wait();
                                  

                                  When I close the app using X button, I see on debuq "return", but application is still wait on thread->wait();

                                  KroMignonK Offline
                                  KroMignonK Offline
                                  KroMignon
                                  wrote on last edited by
                                  #16

                                  @qwe3 said in How to stop QThread?:

                                  But can I send signals from the second thread ( long operations ) like current progress? I never used QtConcurrent.

                                  I have no clue about what you try to do, so here is a "generic" way to do.
                                  Create a QRunnable class, for example:

                                  class Work : public QRunnable
                                  {
                                  public:
                                      Work():mPromise(nullptr) {}
                                      ~Work()
                                      {
                                          delete mPromise;
                                      }
                                  
                                      void run()
                                      {
                                          int loopEnd = qrand();
                                          int loopCount = 0;
                                  
                                          if(mPromise)
                                          {
                                              mPromise->reportStarted();
                                              mPromise->setProgressRange(0, loopEnd);
                                              mPromise->setProgressValue(0);
                                          }
                                          QTextStream out(stdout);
                                  
                                          while (loopCount < loopEnd) {
                                              ++loopCount;
                                              if(mPromise)
                                              {
                                                  if(mPromise->isCanceled())
                                                      break;
                                                  mPromise->setProgressValueAndText(loopCount, QString("Importing %1 frame from: %2...").arg(loopCount).arg(loopEnd));
                                              }
                                  
                                              out << "loopCount: " << loopCount << endl;
                                  
                                              QThread::msleep(250);
                                          }
                                          if(mPromise)
                                              mPromise->reportFinished();
                                      }
                                  
                                      QFuture<void> getFuture()
                                      {
                                          // create future interface to be able to send progression
                                          if(!mPromise) {
                                              mPromise = new QFutureInterface<void>();
                                              mPromise->setThreadPool(QThreadPool::globalInstance());
                                              mPromise->setRunnable(this);
                                          }
                                          return mPromise->future();
                                      }
                                  
                                  private:
                                      QFutureInterface<void> *mPromise;
                                  };
                                  

                                  And then use it, like this for example:

                                  int main(int argc, char *argv[])
                                  {
                                      QCoreApplication app(argc, argv);
                                  
                                      QFutureWatcher<void> futureWatcherProgress;
                                  
                                      // ==> stop application when future is done
                                      QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::finished, &app, &QCoreApplication::quit);
                                      // ==> stop future on application exit
                                      QObject::connect(&app, &QCoreApplication::aboutToQuit, &futureWatcherProgress, &QFutureWatcher<void>::cancel);
                                  
                                      // follow progression
                                      QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressValueChanged, &app, [](int progressValue){
                                              QTextStream out(stdout);
                                              out << "Progression is" << progressValue << endl;
                                          });
                                          QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressRangeChanged, &app, [](int minimum, int maximum){
                                              QTextStream out(stdout);
                                              out << "Progression range from" << minimum << "to" << maximum << endl;
                                          });
                                          QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressTextChanged, &app, [](const QString &progressText) {
                                              QTextStream out(stdout);
                                              out << "Progression:" << progressText << endl;
                                          });
                                  
                                          // create worker ==> QRunnable are automatically destroyed when finished (cf QRunnable::autoDelete())
                                          auto runnable = new Work();
                                          futureWatcherProgress.setFuture(runnable->getFuture());
                                      
                                         return app.exec();
                                  }

                                  It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                  1 Reply Last reply
                                  0
                                  • Q Offline
                                    Q Offline
                                    qwe3
                                    wrote on last edited by qwe3
                                    #17

                                    @KroMignon Thank you for your code, but I don't understand how that can help me.

                                    I change a little your code ( I never before used QFuture etc. so maybe I do something wrong ):

                                    runnable->run(); after futureWatcherProgress.setFuture(runnable->getFuture());
                                    so I have:

                                                ...
                                                auto runnable = new Work();
                                    
                                                futureWatcherProgress.setFuture(runnable->getFuture());
                                      
                                                runnable->run();
                                    

                                    And I add MainWindow like this:

                                            QApplication app(argc, argv);
                                            MainWindow w;
                                            w.show();
                                            return app.exec();
                                    

                                    And move code, which was in main.cpp to mainWindow like this:

                                    MainWindow::MainWindow(QWidget *parent)
                                        : QMainWindow(parent)
                                        , ui(new Ui::MainWindow)
                                    {
                                        ui->setupUi(this);
                                        QTimer::singleShot(1000, this, &MainWindow::fun1);
                                    }
                                    
                                    MainWindow::~MainWindow()
                                    {
                                        delete ui;
                                    }
                                    
                                    void MainWindow::fun1()
                                    {
                                        QFutureWatcher<void> futureWatcherProgress;
                                    
                                        // ==> stop application when future is done
                                        QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::finished, qApp, &QCoreApplication::quit);
                                        // ==> stop future on application exit
                                        QObject::connect(qApp, &QCoreApplication::aboutToQuit, &futureWatcherProgress, &QFutureWatcher<void>::cancel);
                                    
                                        // follow progression
                                        QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressValueChanged, qApp, [](int progressValue){
                                                QTextStream out(stdout);
                                                out << "Progression is" << progressValue << endl;
                                            });
                                            QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressRangeChanged, qApp, [](int minimum, int maximum){
                                                QTextStream out(stdout);
                                                out << "Progression range from" << minimum << "to" << maximum << endl;
                                            });
                                            QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressTextChanged, qApp, [](const QString &progressText) {
                                                QTextStream out(stdout);
                                                out << "Progression:" << progressText << endl;
                                            });
                                    
                                            // create worker ==> QRunnable are automatically destroyed when finished (cf QRunnable::autoDelete())
                                            auto runnable = new Work();
                                    
                                            futureWatcherProgress.setFuture(runnable->getFuture());
                                    
                                            runnable->run();
                                    }
                                    

                                    And this code freeze GUI ( mainWindow ). I add second thread to unfreeze GUI.

                                    KroMignonK 1 Reply Last reply
                                    0
                                    • Q qwe3

                                      @KroMignon Thank you for your code, but I don't understand how that can help me.

                                      I change a little your code ( I never before used QFuture etc. so maybe I do something wrong ):

                                      runnable->run(); after futureWatcherProgress.setFuture(runnable->getFuture());
                                      so I have:

                                                  ...
                                                  auto runnable = new Work();
                                      
                                                  futureWatcherProgress.setFuture(runnable->getFuture());
                                        
                                                  runnable->run();
                                      

                                      And I add MainWindow like this:

                                              QApplication app(argc, argv);
                                              MainWindow w;
                                              w.show();
                                              return app.exec();
                                      

                                      And move code, which was in main.cpp to mainWindow like this:

                                      MainWindow::MainWindow(QWidget *parent)
                                          : QMainWindow(parent)
                                          , ui(new Ui::MainWindow)
                                      {
                                          ui->setupUi(this);
                                          QTimer::singleShot(1000, this, &MainWindow::fun1);
                                      }
                                      
                                      MainWindow::~MainWindow()
                                      {
                                          delete ui;
                                      }
                                      
                                      void MainWindow::fun1()
                                      {
                                          QFutureWatcher<void> futureWatcherProgress;
                                      
                                          // ==> stop application when future is done
                                          QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::finished, qApp, &QCoreApplication::quit);
                                          // ==> stop future on application exit
                                          QObject::connect(qApp, &QCoreApplication::aboutToQuit, &futureWatcherProgress, &QFutureWatcher<void>::cancel);
                                      
                                          // follow progression
                                          QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressValueChanged, qApp, [](int progressValue){
                                                  QTextStream out(stdout);
                                                  out << "Progression is" << progressValue << endl;
                                              });
                                              QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressRangeChanged, qApp, [](int minimum, int maximum){
                                                  QTextStream out(stdout);
                                                  out << "Progression range from" << minimum << "to" << maximum << endl;
                                              });
                                              QObject::connect(&futureWatcherProgress, &QFutureWatcher<void>::progressTextChanged, qApp, [](const QString &progressText) {
                                                  QTextStream out(stdout);
                                                  out << "Progression:" << progressText << endl;
                                              });
                                      
                                              // create worker ==> QRunnable are automatically destroyed when finished (cf QRunnable::autoDelete())
                                              auto runnable = new Work();
                                      
                                              futureWatcherProgress.setFuture(runnable->getFuture());
                                      
                                              runnable->run();
                                      }
                                      

                                      And this code freeze GUI ( mainWindow ). I add second thread to unfreeze GUI.

                                      KroMignonK Offline
                                      KroMignonK Offline
                                      KroMignon
                                      wrote on last edited by KroMignon
                                      #18

                                      @qwe3 said in How to stop QThread?:

                                      I change a little your code ( I never before used QFuture etc. so maybe I do something wrong ):
                                      runnable->run(); after futureWatcherProgress.setFuture(runnable->getFuture());

                                      Okay, my code was o a little bit too rough, so I will be more explicit:

                                      • a create a class based on QRunnable to be able to use it with QThreadPool.
                                      • in the method getFuture(), the class instance is transformed to future a will run in next thread available the thread pool. So the run() method will be called a soon as possible
                                      • after that I record the QFuture instance returned into the QFutureWatcher instance to be aware about state changes.

                                      Your fun1() don't made sense; the QFutureWatcher is a local variable which will be delete at function end!
                                      Change it like this:

                                      void MainWindow::fun1()
                                      {
                                          // do NOT use a local variable!!!
                                          auto futureWatcherProgress = new QFutureWatcher<void>();
                                      
                                          // ==> delete QFuteWatcher instance instance when process done
                                          connect(futureWatcherProgress, &QFutureWatcher<void>::finished, futureWatcherProgress, [futureWatcherProgress]() {
                                              futureWatcherProgress->deleteLater();
                                              qDebug() << "Processing done.";
                                          });
                                          // ==> stop future on application exit
                                          connect(qApp, &QCoreApplication::aboutToQuit, futureWatcherProgress, &QFutureWatcher<void>::cancel);
                                      
                                          // follow progression
                                          connect(futureWatcherProgress, &QFutureWatcher<void>::progressValueChanged, this, [](int progressValue){
                                              qDebug() << "Progression is" << progressValue;
                                          });
                                          connect(futureWatcherProgress, &QFutureWatcher<void>::progressRangeChanged, this, [](int minimum, int maximum){
                                              qDebug()<< "Progression range from" << minimum << "to" << maximum;
                                          });
                                          connect(&futureWatcherProgress, &QFutureWatcher<void>::progressTextChanged, qApp, [](const QString &progressText) {
                                              qDebug() << "Progression:" << progressText;
                                          });
                                      
                                          // create worker ==> QRunnable are automatically destroyed when finished (cf QRunnable::autoDelete())
                                          auto runnable = new Work();
                                      
                                          // register future and start processing
                                          futureWatcherProgress->setFuture(runnable->getFuture());
                                      }
                                      

                                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                                      1 Reply Last reply
                                      0

                                      • Login

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