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 close the programme when running a qtconcurrent from another thread
Forum Updated to NodeBB v4.3 + New Features

How to close the programme when running a qtconcurrent from another thread

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 5 Posters 2.7k 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.
  • M Offline
    M Offline
    Mandeep.Chaudhary
    wrote on last edited by Mandeep.Chaudhary
    #1

    Hi,

    The point of this question is only how to stop the programme if you are running QtConcurrent from second thread.

    I am running a programme that has multithreading . The programme firstly has a main / UI thread running in it. In this programme I have a worker and handler class.

    The worker class is having a simulate function which simply generates the random number. The simulate function continuously generates the number without blocking any thread i.e. via Qtconcurrent.

    From the main/UI thread I have put this worker class into new thread. The handler class is running in main /UI thread and is responsible to communicate with worker class running in other thread via signal slot.

    So far everything is ok.

    Problem starts when i try to close the programme by simply clicking on app cross button. The programme sort of hangs it does not close. However when i dont put worker in another class . The Same codes work and programme exits with 0.

    So my question is how to stop Qtconcurrent is another thread and finally close the another thread aswell.

    Thank You.

    main.cpp

    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        QThread l_newThread;
    
        Worker* l_worker = new Worker();
        handler * l_handler = new handler();
    
        l_worker->moveToThread(&l_newThread);
    
        QObject::connect(&l_newThread, &QThread::started, l_worker, &Worker::Init);
    
        QObject::connect(l_handler,&handler::toStop_Signal,&l_newThread, &QThread::quit);
        QObject::connect(l_worker, &Worker::toStop_Signal_Worker, l_handler,&handler::toStop_Slot);
        QObject::connect(&app,&QCoreApplication::aboutToQuit, l_worker, &Worker::stop);
       // QObject::connect(&app,&QCoreApplication::aboutToQuit, &l_newThread, &QThread::quit);
    
        l_newThread.start();
       // l_worker->Init();
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
        if (engine.rootObjects().isEmpty())
            return -1;
    
        int result = app.exec();
    
        l_newThread.wait();
    
        return result;
    }
    
    handler
    
    #include "handler.h"
    
    handler::handler(QObject *parent) : QObject(parent)
    {
    
    }
    
    void handler::toStop_Slot()
    {
        emit toStop_Signal();
    }
    

    worker.cpp

    #include "worker.h"
    
    Worker::Worker(QObject *parent) : QObject(parent)
    {
    
    }
    
    void Worker:: Init()
    {
        m_simulation = true;
        simulate();
    }
    
    void Worker::simulate()
    {
        QtConcurrent::run([this]{
            QRandomGenerator generator;
    
            while (m_simulation) {
    
    
                qint32 t = generator.bounded(0,100);
                qDebug() << t;
    
    
                qDebug() << "sleeping for 1 second";
                QThread::sleep(1);
            }
    
            if (!m_simulation) {
                qDebug() << "Killing the concurrent thread";
                //  QThread::currentThread()->exit();
                emit toStop_Signal_Worker();
            }
        });
    
    }
    
    void Worker::stop()
    {
        m_simulation = false;
    }
    

    results

    QML debugging is enabled. Only use this in a safe environment.
    19
    sleeping for 1 second
    55
    sleeping for 1 second
    70
    sleeping for 1 second
    69
    sleeping for 1 second
    Killing the concurrent thread
    
    1 Reply Last reply
    0
    • G Offline
      G Offline
      Gerd
      wrote on last edited by
      #2

      Hi,
      you are doing a thread in a thread...
      QtConcurrent::run creates a thread for you, no needance for putting the worker object into another thread.

      You can do it like this:

      class Worker : public QObject{
         bool m_simulation;
      public:
         QFuture<void> future;
         Worker(QObject *parent=0);
         void Init();
         void simulate();
         void stop();
      };
      Worker::Worker(QObject *parent) : QObject(parent){}
      
      void Worker::Init()
      {
         m_simulation = true;
         simulate();
      }
      
      void Worker::simulate()
      {
         future = QtConcurrent::run([this] {
            QRandomGenerator generator;
      
            while (m_simulation) {
      
      
               qint32 t = generator.bounded(0, 100);
               qDebug() << t;
      
      
               qDebug() << "sleeping for 1 second";
               QThread::sleep(1);
            }
      
            if (!m_simulation) {
               qDebug() << "Killing the concurrent thread";
               //  QThread::currentThread()->exit();
               //emit toStop_Signal_Worker();
            }
         });
      
      }
      
      void Worker::stop()
      {
         m_simulation = false;
      }
      
      

      and then in your main:

         Worker *l_worker = new Worker();
         l_worker->Init();
         QObject::connect(&a, &QCoreApplication::aboutToQuit, l_worker, &Worker::stop);
         engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
      
          if (engine.rootObjects().isEmpty())
              return -1;
      
          int result = app.exec();
      
         l_worker->future.waitForFinished();
      
      
      M 1 Reply Last reply
      2
      • G Gerd

        Hi,
        you are doing a thread in a thread...
        QtConcurrent::run creates a thread for you, no needance for putting the worker object into another thread.

        You can do it like this:

        class Worker : public QObject{
           bool m_simulation;
        public:
           QFuture<void> future;
           Worker(QObject *parent=0);
           void Init();
           void simulate();
           void stop();
        };
        Worker::Worker(QObject *parent) : QObject(parent){}
        
        void Worker::Init()
        {
           m_simulation = true;
           simulate();
        }
        
        void Worker::simulate()
        {
           future = QtConcurrent::run([this] {
              QRandomGenerator generator;
        
              while (m_simulation) {
        
        
                 qint32 t = generator.bounded(0, 100);
                 qDebug() << t;
        
        
                 qDebug() << "sleeping for 1 second";
                 QThread::sleep(1);
              }
        
              if (!m_simulation) {
                 qDebug() << "Killing the concurrent thread";
                 //  QThread::currentThread()->exit();
                 //emit toStop_Signal_Worker();
              }
           });
        
        }
        
        void Worker::stop()
        {
           m_simulation = false;
        }
        
        

        and then in your main:

           Worker *l_worker = new Worker();
           l_worker->Init();
           QObject::connect(&a, &QCoreApplication::aboutToQuit, l_worker, &Worker::stop);
           engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        
            if (engine.rootObjects().isEmpty())
                return -1;
        
            int result = app.exec();
        
           l_worker->future.waitForFinished();
        
        
        M Offline
        M Offline
        Mandeep.Chaudhary
        wrote on last edited by Mandeep.Chaudhary
        #3

        @Gerd Thank You. I know running it directly wont be a problem as you illustrated in your example.

        I have also mentioned this in my first post. "The programme sort of hangs it does not close. However when i dont put worker in another class . The Same codes work and programme exits with 0."

        This example/ question is a part of bigger programme. The basic Idea of this example is to know how to stop programme when programme is having an additional thread and qtconcurrent is running in that. Then how to stop the programme.

        jsulmJ 1 Reply Last reply
        0
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          Does QThread::sleep process events?
          If not you need to process events in your thread. Try putting doing this:

          ...
          QCoreApplication::processEvents();
          QThread::sleep(1);
          

          C++ is a perfectly valid school of magic.

          M 1 Reply Last reply
          0
          • M Mandeep.Chaudhary

            @Gerd Thank You. I know running it directly wont be a problem as you illustrated in your example.

            I have also mentioned this in my first post. "The programme sort of hangs it does not close. However when i dont put worker in another class . The Same codes work and programme exits with 0."

            This example/ question is a part of bigger programme. The basic Idea of this example is to know how to stop programme when programme is having an additional thread and qtconcurrent is running in that. Then how to stop the programme.

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

            @Mandeep-Chaudhary Can you explain why you're using QtConcurrent::run() in a thread? What is the point? You're already in your second thread, why creating a third one from the second?

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

            M 1 Reply Last reply
            3
            • jsulmJ jsulm

              @Mandeep-Chaudhary Can you explain why you're using QtConcurrent::run() in a thread? What is the point? You're already in your second thread, why creating a third one from the second?

              M Offline
              M Offline
              Mandeep.Chaudhary
              wrote on last edited by Mandeep.Chaudhary
              #6

              @jsulm Thank you for your reply. Question here is not "What is the point? You're already in your second thread, why creating a third one from the second?" and so on.

              Question is very simple as QtConcurrent::run() is executed from second thread which is working (as shown above) then
              how to stop it. We can discuss the philoshopical things at later stage. First its important to utilize all possibilities in QT.

              1 Reply Last reply
              0
              • fcarneyF fcarney

                Does QThread::sleep process events?
                If not you need to process events in your thread. Try putting doing this:

                ...
                QCoreApplication::processEvents();
                QThread::sleep(1);
                
                M Offline
                M Offline
                Mandeep.Chaudhary
                wrote on last edited by Mandeep.Chaudhary
                #7

                @fcarney Thank You for your reply. I am afraid I did not understand what you mean by "you need to process events in your thread". If I assume you mean to say something similar as mentioned in the first reply then for sure we are going of the topic.

                J.HilkJ 1 Reply Last reply
                0
                • M Mandeep.Chaudhary

                  @fcarney Thank You for your reply. I am afraid I did not understand what you mean by "you need to process events in your thread". If I assume you mean to say something similar as mentioned in the first reply then for sure we are going of the topic.

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

                  @Mandeep-Chaudhary
                  QtConCurrent::run, returns a QFuture, store this in a member variable and on worker destruction, check if the QFuture is still valid and running.
                  If it is, call cancel()followed by waitForFinished()


                  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.

                  M 1 Reply Last reply
                  2
                  • G Offline
                    G Offline
                    Gerd
                    wrote on last edited by
                    #9

                    even if i think thats not usefull....

                       QThread l_newThread;
                       Worker *l_worker = new Worker();
                       l_worker->moveToThread(&l_newThread);
                       l_newThread.start();
                       l_worker->Init();
                       QObject::connect(&a, &QCoreApplication::aboutToQuit, l_worker, &Worker::stop);
                       engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                    
                        if (engine.rootObjects().isEmpty())
                            return -1;
                    
                        int result = app.exec();
                       l_worker->future.waitForFinished();
                       l_newThread.quit();
                    
                    
                    1 Reply Last reply
                    0
                    • J.HilkJ J.Hilk

                      @Mandeep-Chaudhary
                      QtConCurrent::run, returns a QFuture, store this in a member variable and on worker destruction, check if the QFuture is still valid and running.
                      If it is, call cancel()followed by waitForFinished()

                      M Offline
                      M Offline
                      Mandeep.Chaudhary
                      wrote on last edited by
                      #10

                      @J-Hilk and @Gerd Thank You for your replies. I combined your logic with handler and now it works.

                      Basically now programme makes sure first qtconcurrent is stopped and then the second thread.

                      int main(int argc, char *argv[])
                      {
                          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                      
                          QGuiApplication app(argc, argv);
                      
                          QQmlApplicationEngine engine;
                      
                          QThread l_newThread;
                      
                          Worker* l_worker = new Worker();
                          handler * l_handler = new handler();
                      
                          l_worker->moveToThread(&l_newThread);
                      
                          QObject::connect(&l_newThread, &QThread::started, l_worker, &Worker::Init);
                      
                          QObject::connect(l_handler,&handler::toStop_Signal,l_worker, &Worker::stop);
                          QObject::connect(&app,&QCoreApplication::aboutToQuit, l_handler,&handler::toStop_Slot);
                      
                          l_newThread.start();
                      
                          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                      
                          if (engine.rootObjects().isEmpty())
                              return -1;
                      
                          int result = app.exec();
                      
                          l_worker->future.waitForFinished();
                          l_newThread.quit();
                          l_newThread.wait();
                      
                          return result;
                      }
                      
                      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