Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QThread infinite loop
Forum Updated to NodeBB v4.3 + New Features

QThread infinite loop

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 5 Posters 2.1k Views 2 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.
  • S Offline
    S Offline
    salvatore.proxy
    wrote on last edited by
    #1

    Hello everyone,
    How do I perform an infinity function with an interval?
    When I inherit QThread and override run() I call exec() inside it, but it blocks everything that comes after.

    MyClass::MyClass():
        i(0)
    {
        qDebug() << " MyClass() " << QThread::currentThread();
        moveToThread(this);
        start();
    }
    
    void MyClass::run(){
        qDebug() << "MyClass::run() " << QThread::currentThread();
        qDebug() << "before exec()";
    
        exec();
        for (int var = 0; var < 5; ++var) {
            emit emitMyClass("MyClass" + QString::number(i++));
            qDebug() << " Emit! " <<QThread::currentThread();
            QThread::sleep(5);
        }
        qDebug() << "after exec()";
    }
    
    

    thanks in advance,
    Sal

    C S 2 Replies Last reply
    0
    • S salvatore.proxy

      Hello everyone,
      How do I perform an infinity function with an interval?
      When I inherit QThread and override run() I call exec() inside it, but it blocks everything that comes after.

      MyClass::MyClass():
          i(0)
      {
          qDebug() << " MyClass() " << QThread::currentThread();
          moveToThread(this);
          start();
      }
      
      void MyClass::run(){
          qDebug() << "MyClass::run() " << QThread::currentThread();
          qDebug() << "before exec()";
      
          exec();
          for (int var = 0; var < 5; ++var) {
              emit emitMyClass("MyClass" + QString::number(i++));
              qDebug() << " Emit! " <<QThread::currentThread();
              QThread::sleep(5);
          }
          qDebug() << "after exec()";
      }
      
      

      thanks in advance,
      Sal

      C Offline
      C Offline
      ChrisW67
      wrote on last edited by
      #2

      When I inherit QThread and override run() I call exec() inside it, but it blocks everything that comes after.

      Exactly as documented.

      You do not need a thread to do periodic execution of some action.

      QTimer *timer = new QTimer(this);
      connect(timer, &QTimer::timeout(), someQObject, &SomeQObjectClass::timeoutSlot());
      timer->setInterval(5); // milliseconds
      timer->start();
      

      Whatever happens inside the slot needs to be short running. There is no loop in the slot. This object should maintain a run count (to replace var) and either stop the timer when 5 is reached, or reset the count to 0 etc.

      1 Reply Last reply
      5
      • S salvatore.proxy

        Hello everyone,
        How do I perform an infinity function with an interval?
        When I inherit QThread and override run() I call exec() inside it, but it blocks everything that comes after.

        MyClass::MyClass():
            i(0)
        {
            qDebug() << " MyClass() " << QThread::currentThread();
            moveToThread(this);
            start();
        }
        
        void MyClass::run(){
            qDebug() << "MyClass::run() " << QThread::currentThread();
            qDebug() << "before exec()";
        
            exec();
            for (int var = 0; var < 5; ++var) {
                emit emitMyClass("MyClass" + QString::number(i++));
                qDebug() << " Emit! " <<QThread::currentThread();
                QThread::sleep(5);
            }
            qDebug() << "after exec()";
        }
        
        

        thanks in advance,
        Sal

        S Offline
        S Offline
        salvatore.proxy
        wrote on last edited by
        #3

        @salvatore-proxy
        Thanks @c-cardona ,
        the example above of the for going from 0 to 5 was an example , also imagine it as a

        while(1){
          doSOmethings
        }
        

        I need to periodically perform a function but in a separate thread, ie,
        I have the main thread doing things, I need to create a new thread where within it I perform a function periodically, I have succeeded by overriding the run() method

        void run(){
            init();
            while(true)
            {
                periodicFunction();
                QThread::sleep(2);
            }
        }
        

        this way it works but I don't have the event loop active via exec();

        void run(){
            init();
            exec();   // Start event loop
            while(true)
            {
                periodicFunction();
                QThread::sleep(2);
            }
        }
        

        exec() after this instruction nothing is executed, only after calling exit() does the flow of the run() function resume;

        JonBJ 1 Reply Last reply
        0
        • S salvatore.proxy

          @salvatore-proxy
          Thanks @c-cardona ,
          the example above of the for going from 0 to 5 was an example , also imagine it as a

          while(1){
            doSOmethings
          }
          

          I need to periodically perform a function but in a separate thread, ie,
          I have the main thread doing things, I need to create a new thread where within it I perform a function periodically, I have succeeded by overriding the run() method

          void run(){
              init();
              while(true)
              {
                  periodicFunction();
                  QThread::sleep(2);
              }
          }
          

          this way it works but I don't have the event loop active via exec();

          void run(){
              init();
              exec();   // Start event loop
              while(true)
              {
                  periodicFunction();
                  QThread::sleep(2);
              }
          }
          

          exec() after this instruction nothing is executed, only after calling exit() does the flow of the run() function resume;

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @salvatore-proxy
          You can use the event loop in exec() plus a QTimer to do the same thing as your while(true) sleep();. You would not want to use both of these, either-or.

          S 1 Reply Last reply
          2
          • JonBJ JonB

            @salvatore-proxy
            You can use the event loop in exec() plus a QTimer to do the same thing as your while(true) sleep();. You would not want to use both of these, either-or.

            S Offline
            S Offline
            salvatore.proxy
            wrote on last edited by salvatore.proxy
            #5

            @JonB
            something like

            void run(){
                init();
                timer = new QTimer();
                timer->setInterval(1000);
                QObject::connect(timer, &QTimer::timeout, this, &MyClass::periodicFunction);
                timer->start();
                exec();   // Start event loop
            }
            

            I used the run() method by also calling exec() so I have event loops to use signals and slots, but I have an internal timer that calls my run periodically, do you agree?

            JonBJ 1 Reply Last reply
            0
            • S salvatore.proxy

              @JonB
              something like

              void run(){
                  init();
                  timer = new QTimer();
                  timer->setInterval(1000);
                  QObject::connect(timer, &QTimer::timeout, this, &MyClass::periodicFunction);
                  timer->start();
                  exec();   // Start event loop
              }
              

              I used the run() method by also calling exec() so I have event loops to use signals and slots, but I have an internal timer that calls my run periodically, do you agree?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @salvatore-proxy
              The code looks fine. I'm afraid I don't understand what the question is about an internal timer.

              S 1 Reply Last reply
              0
              • JonBJ JonB

                @salvatore-proxy
                The code looks fine. I'm afraid I don't understand what the question is about an internal timer.

                S Offline
                S Offline
                salvatore.proxy
                wrote on last edited by
                #7

                @JonB
                My question is it right to use a QTimer within a Qthread?
                My needs are to:

                • launch a new thread that can handle slots and signals ( event loop is needed for this)
                • run in the new thread the slots connected to signals from other threads and periodically run a task that generates a signals to other threads
                JonBJ 1 Reply Last reply
                0
                • S salvatore.proxy

                  @JonB
                  My question is it right to use a QTimer within a Qthread?
                  My needs are to:

                  • launch a new thread that can handle slots and signals ( event loop is needed for this)
                  • run in the new thread the slots connected to signals from other threads and periodically run a task that generates a signals to other threads
                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @salvatore-proxy
                  Yes using QTimer in QThread (with exec() running) is fine and sounds like what you want for a periodic task.

                  1 Reply Last reply
                  2
                  • S Offline
                    S Offline
                    SimonSchroeder
                    wrote on last edited by
                    #9

                    exec() starts an event loop just like you already do when calling app.exec() inside main(). This is the reason why it blocks.

                    Overriding QThread::run() is the Java way to do multi-threading. Qt started moving away from this (and even the documentation does not teach this approach as the normal one anymore). The default implementation of run() will just call exec(). Instead, Qt promotes a worker object approach. Inherit from QObject and implement a slot (or just use a lambda if that is sufficient). The QTimer object would also then be created from another thread and then moved into the thread using QObject::moveToThread().

                    You source should then look something like this:

                    class MyClass : public QObject
                    {
                    Q_OBJECT
                    public slots:
                      void periodicFunction() {...}
                    };
                    //-----8<---------------------------------------------
                    QThread *thread = new QThread();
                    thread->start(); // could also be done later
                    
                    MyClass *obj = new MyClass();
                    obj->moveToThread(thread);
                    
                    QTimer *timer = new QTimer();
                    timer->setInterval(1000);
                    QObject::connect(timer, &QTimer::timout, obj, &MyClass::periodicFunction);
                    timer->moveToThread(thread);
                    timer->start();
                    

                    If I'm not mistaken, even if you don't move the timer into the thread (but do move the instance of MyClass) it will work correctly. The timeout would then fire inside the main thread, but signal/slot connection will work across thread boundaries. And because obj is located inside the thread (because of moveToThread()) the slot will be executed with the separate thread.

                    If you just want a simple function, you could also connect to a lambda instead:

                    QObject::connect(timer, &QTimer::timeout, [](){ ...});
                    

                    However, the lambda is not located in any specific thread. This would mean you have to move the timer again into the thread (whereas before this was optional).

                    You could, however, provide a context object for the lambda. Maybe this would start execution of the lambda inside the corresponding thread even if the time lives inside the main thread:

                    QObject::connect(timer, &QTimer::timeout, thread, [](){ ... });
                    

                    We heavily rely on plain QThreads (without inheritance) in our software. Usually, we don't need repeated calls. An easy start is QThread::create([]() {...})->start();. But, you need to make sure to delete the thread itself at the end. For a worker thread you can use QMetaObject::invokeMethod(thread, []() {...}); for a one-time slot to be handled by a running QThread.

                    JonBJ jeremy_kJ 2 Replies Last reply
                    1
                    • S SimonSchroeder

                      exec() starts an event loop just like you already do when calling app.exec() inside main(). This is the reason why it blocks.

                      Overriding QThread::run() is the Java way to do multi-threading. Qt started moving away from this (and even the documentation does not teach this approach as the normal one anymore). The default implementation of run() will just call exec(). Instead, Qt promotes a worker object approach. Inherit from QObject and implement a slot (or just use a lambda if that is sufficient). The QTimer object would also then be created from another thread and then moved into the thread using QObject::moveToThread().

                      You source should then look something like this:

                      class MyClass : public QObject
                      {
                      Q_OBJECT
                      public slots:
                        void periodicFunction() {...}
                      };
                      //-----8<---------------------------------------------
                      QThread *thread = new QThread();
                      thread->start(); // could also be done later
                      
                      MyClass *obj = new MyClass();
                      obj->moveToThread(thread);
                      
                      QTimer *timer = new QTimer();
                      timer->setInterval(1000);
                      QObject::connect(timer, &QTimer::timout, obj, &MyClass::periodicFunction);
                      timer->moveToThread(thread);
                      timer->start();
                      

                      If I'm not mistaken, even if you don't move the timer into the thread (but do move the instance of MyClass) it will work correctly. The timeout would then fire inside the main thread, but signal/slot connection will work across thread boundaries. And because obj is located inside the thread (because of moveToThread()) the slot will be executed with the separate thread.

                      If you just want a simple function, you could also connect to a lambda instead:

                      QObject::connect(timer, &QTimer::timeout, [](){ ...});
                      

                      However, the lambda is not located in any specific thread. This would mean you have to move the timer again into the thread (whereas before this was optional).

                      You could, however, provide a context object for the lambda. Maybe this would start execution of the lambda inside the corresponding thread even if the time lives inside the main thread:

                      QObject::connect(timer, &QTimer::timeout, thread, [](){ ... });
                      

                      We heavily rely on plain QThreads (without inheritance) in our software. Usually, we don't need repeated calls. An easy start is QThread::create([]() {...})->start();. But, you need to make sure to delete the thread itself at the end. For a worker thread you can use QMetaObject::invokeMethod(thread, []() {...}); for a one-time slot to be handled by a running QThread.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @SimonSchroeder said in QThread infinite loop:

                      If I'm not mistaken, even if you don't move the timer into the thread (but do move the instance of MyClass) it will work correctly. The timeout would then fire inside the main thread, but signal/slot connection will work across thread boundaries

                      Question: Suppose the main thread is (perhaps incorrectly) "blocked" (or busy doing some computation). In that case although the signal is connected "queued across thread" would the signal not be acted on/the slot get queued for execution in the thread at the instant of the emit, would it have to wait till the next time the main thread's event loop is hit (whenever that might be)?

                      S 1 Reply Last reply
                      0
                      • JonBJ JonB

                        @SimonSchroeder said in QThread infinite loop:

                        If I'm not mistaken, even if you don't move the timer into the thread (but do move the instance of MyClass) it will work correctly. The timeout would then fire inside the main thread, but signal/slot connection will work across thread boundaries

                        Question: Suppose the main thread is (perhaps incorrectly) "blocked" (or busy doing some computation). In that case although the signal is connected "queued across thread" would the signal not be acted on/the slot get queued for execution in the thread at the instant of the emit, would it have to wait till the next time the main thread's event loop is hit (whenever that might be)?

                        S Offline
                        S Offline
                        SimonSchroeder
                        wrote on last edited by
                        #11

                        @JonB said in QThread infinite loop:

                        would it have to wait till the next time the main thread's event loop is hit

                        From my understanding: yes.

                        1 Reply Last reply
                        1
                        • S SimonSchroeder

                          exec() starts an event loop just like you already do when calling app.exec() inside main(). This is the reason why it blocks.

                          Overriding QThread::run() is the Java way to do multi-threading. Qt started moving away from this (and even the documentation does not teach this approach as the normal one anymore). The default implementation of run() will just call exec(). Instead, Qt promotes a worker object approach. Inherit from QObject and implement a slot (or just use a lambda if that is sufficient). The QTimer object would also then be created from another thread and then moved into the thread using QObject::moveToThread().

                          You source should then look something like this:

                          class MyClass : public QObject
                          {
                          Q_OBJECT
                          public slots:
                            void periodicFunction() {...}
                          };
                          //-----8<---------------------------------------------
                          QThread *thread = new QThread();
                          thread->start(); // could also be done later
                          
                          MyClass *obj = new MyClass();
                          obj->moveToThread(thread);
                          
                          QTimer *timer = new QTimer();
                          timer->setInterval(1000);
                          QObject::connect(timer, &QTimer::timout, obj, &MyClass::periodicFunction);
                          timer->moveToThread(thread);
                          timer->start();
                          

                          If I'm not mistaken, even if you don't move the timer into the thread (but do move the instance of MyClass) it will work correctly. The timeout would then fire inside the main thread, but signal/slot connection will work across thread boundaries. And because obj is located inside the thread (because of moveToThread()) the slot will be executed with the separate thread.

                          If you just want a simple function, you could also connect to a lambda instead:

                          QObject::connect(timer, &QTimer::timeout, [](){ ...});
                          

                          However, the lambda is not located in any specific thread. This would mean you have to move the timer again into the thread (whereas before this was optional).

                          You could, however, provide a context object for the lambda. Maybe this would start execution of the lambda inside the corresponding thread even if the time lives inside the main thread:

                          QObject::connect(timer, &QTimer::timeout, thread, [](){ ... });
                          

                          We heavily rely on plain QThreads (without inheritance) in our software. Usually, we don't need repeated calls. An easy start is QThread::create([]() {...})->start();. But, you need to make sure to delete the thread itself at the end. For a worker thread you can use QMetaObject::invokeMethod(thread, []() {...}); for a one-time slot to be handled by a running QThread.

                          jeremy_kJ Offline
                          jeremy_kJ Offline
                          jeremy_k
                          wrote on last edited by
                          #12

                          @SimonSchroeder said in QThread infinite loop:

                          //-----8<---------------------------------------------
                          QThread *thread = new QThread();
                          thread->start(); // could also be done later
                          
                          MyClass *obj = new MyClass();
                          obj->moveToThread(thread);
                          
                          QTimer *timer = new QTimer();
                          timer->setInterval(1000);
                          QObject::connect(timer, &QTimer::timout, obj, &MyClass::periodicFunction);
                          timer->moveToThread(thread);
                          timer->start();
                          

                          Multithreading is hard! The timer->start() should come before timer->moveToThread(). I would also establish the connection from the QTimer instance to MyClass instance before moving the later. It's paranoia in this case, but prevents connecting to deleted objects in some realistic scenarios.

                          Asking a question about code? http://eel.is/iso-c++/testcase/

                          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