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. Understaning when Qt's Event Loop processes events
Forum Update on Tuesday, May 27th 2025

Understaning when Qt's Event Loop processes events

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 1.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.
  • P Offline
    P Offline
    pjorourke05
    wrote on last edited by pjorourke05
    #1

    So I created a test application to figure out more about how Qt's Event loops is working. So I have a class called testclass and this class objective is add a message to the que every 100ms. Then the class simulates sending a message outbound by simulating the wait process. For testing purpose I wait for a lone time 2 seconds. During that wait period I would expect the queue would be getting filled because every 100ms I should be adding a message but this does not happen msgs dont get added to the queue until my simulated wait is complete. So I am confused on when Qt processes its event loop.. How can a timers timeout slot get handled if something else is being processed. When does the event loop decide that its okay to process an event in between function calls? I am just misunderstanding how this process works and any help would be greatly appreciated.

    testclass.h

    #define TESTCLASS_H
    
    #include <QObject>
    #include <QTimer>
    #include <QSemaphore>
    #include <QQueue>
    class testclass : public QObject
    {
        Q_OBJECT
    public:
        QTimer secondMsgTimer;
        QQueue<QString> msgqueue;
        explicit testclass(QObject *parent = nullptr);
        void addMsgToSend(QString msg);
        void sendMsg();
        void wait();
    private slots:
        void secondMsgTimerHandler();
    public slots:
        void init();
    
    };
    
    #endif // TESTCLASS_H
    

    testclass.cpp

    #include "testclass.h"
    #include <QDebug>
    #include <QThread>
    #include <QCoreApplication>
    
    QSemaphore semaphore(1);
    int msgcount = 0;
    testclass::testclass(QObject *parent) : QObject(parent)
    {
     connect(&secondMsgTimer, SIGNAL(timeout()), SLOT(secondMsgTimerHandler()));
    }
    
    // adds msg to the que
    void testclass::addMsgToSend(QString msg)
    {
        msgqueue.enqueue(msg);
        sendMsg();
    
    }
    void testclass::sendMsg()
    {
        semaphore.acquire();
        QString msg = msgqueue.dequeue();
        //simulate sending a command and waiting for response. I want to be blocking here
        //because in my real code I need to wait for the results of the msg to continue
        qDebug() << "sending msg" << msg;
        wait();
        qDebug() << "got rsp for msg= " << msg;
        semaphore.release();
    }
    
    void testclass::wait()
    {
        //simulate waiting
        QThread::msleep(2000);
    }
    
    void testclass::secondMsgTimerHandler()
    {
        // add a msg to the que every 100ms but this does not happen..
        // this slot is only fired after the wait() function completes which is every 2 seconds
        // why is this? what am I doing wrong? why does the event loop not process events during that 2 seconds
        msgcount++;
        addMsgToSend(QString("This is msg %1").arg(msgcount));
    }
    
    // initilize test class once the event loop is running.
    void testclass::init()
    {
         secondMsgTimer.start(100);
    }
    
    

    main.cpp

    #include <QCoreApplication>
    #include <QTimer>
    #include "testclass.h"
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        //creat test class
        testclass t(&a);
        // init the test class once the event loop is running
        QTimer::singleShot(0,&t,SLOT(init()));
        return a.exec();
    }
    
    
    
    
    
    
    JonBJ 1 Reply Last reply
    0
    • P pjorourke05

      So I created a test application to figure out more about how Qt's Event loops is working. So I have a class called testclass and this class objective is add a message to the que every 100ms. Then the class simulates sending a message outbound by simulating the wait process. For testing purpose I wait for a lone time 2 seconds. During that wait period I would expect the queue would be getting filled because every 100ms I should be adding a message but this does not happen msgs dont get added to the queue until my simulated wait is complete. So I am confused on when Qt processes its event loop.. How can a timers timeout slot get handled if something else is being processed. When does the event loop decide that its okay to process an event in between function calls? I am just misunderstanding how this process works and any help would be greatly appreciated.

      testclass.h

      #define TESTCLASS_H
      
      #include <QObject>
      #include <QTimer>
      #include <QSemaphore>
      #include <QQueue>
      class testclass : public QObject
      {
          Q_OBJECT
      public:
          QTimer secondMsgTimer;
          QQueue<QString> msgqueue;
          explicit testclass(QObject *parent = nullptr);
          void addMsgToSend(QString msg);
          void sendMsg();
          void wait();
      private slots:
          void secondMsgTimerHandler();
      public slots:
          void init();
      
      };
      
      #endif // TESTCLASS_H
      

      testclass.cpp

      #include "testclass.h"
      #include <QDebug>
      #include <QThread>
      #include <QCoreApplication>
      
      QSemaphore semaphore(1);
      int msgcount = 0;
      testclass::testclass(QObject *parent) : QObject(parent)
      {
       connect(&secondMsgTimer, SIGNAL(timeout()), SLOT(secondMsgTimerHandler()));
      }
      
      // adds msg to the que
      void testclass::addMsgToSend(QString msg)
      {
          msgqueue.enqueue(msg);
          sendMsg();
      
      }
      void testclass::sendMsg()
      {
          semaphore.acquire();
          QString msg = msgqueue.dequeue();
          //simulate sending a command and waiting for response. I want to be blocking here
          //because in my real code I need to wait for the results of the msg to continue
          qDebug() << "sending msg" << msg;
          wait();
          qDebug() << "got rsp for msg= " << msg;
          semaphore.release();
      }
      
      void testclass::wait()
      {
          //simulate waiting
          QThread::msleep(2000);
      }
      
      void testclass::secondMsgTimerHandler()
      {
          // add a msg to the que every 100ms but this does not happen..
          // this slot is only fired after the wait() function completes which is every 2 seconds
          // why is this? what am I doing wrong? why does the event loop not process events during that 2 seconds
          msgcount++;
          addMsgToSend(QString("This is msg %1").arg(msgcount));
      }
      
      // initilize test class once the event loop is running.
      void testclass::init()
      {
           secondMsgTimer.start(100);
      }
      
      

      main.cpp

      #include <QCoreApplication>
      #include <QTimer>
      #include "testclass.h"
      
      int main(int argc, char *argv[])
      {
          QCoreApplication a(argc, argv);
          //creat test class
          testclass t(&a);
          // init the test class once the event loop is running
          QTimer::singleShot(0,&t,SLOT(init()));
          return a.exec();
      }
      
      
      
      
      
      
      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @pjorourke05

      QThread::msleep(2000);
      

      This puts the thread to sleep, so it does nothing during that time. Unless you use separate threads in your code --- which you do not --- you can't use this.

      //because in my real code I need to wait for the results of the msg to continue
      wait();

      Try not to organize things this way. When the response arrives, act on it then (signals & slots). If you realyy have to wait, look at QEventLoop::exec(), not sleep.

      P 1 Reply Last reply
      1
      • JonBJ JonB

        @pjorourke05

        QThread::msleep(2000);
        

        This puts the thread to sleep, so it does nothing during that time. Unless you use separate threads in your code --- which you do not --- you can't use this.

        //because in my real code I need to wait for the results of the msg to continue
        wait();

        Try not to organize things this way. When the response arrives, act on it then (signals & slots). If you realyy have to wait, look at QEventLoop::exec(), not sleep.

        P Offline
        P Offline
        pjorourke05
        wrote on last edited by
        #3

        @JonB To clarify.. your stating I am blocking the event loop with my wait() function which inst allowing the timer's timeout signal to fire. What I should do is send the messages async then use a slot to handle when the results of the message are received Which means any logic that relies on the results of a message would go into that slot.

        JonBJ 1 Reply Last reply
        0
        • P pjorourke05

          @JonB To clarify.. your stating I am blocking the event loop with my wait() function which inst allowing the timer's timeout signal to fire. What I should do is send the messages async then use a slot to handle when the results of the message are received Which means any logic that relies on the results of a message would go into that slot.

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

          @pjorourke05
          Yes, sleep is sleep, and sleeping things (including threads) just don't do anything other than sleep :)

          Yes, Qt programming is set up for you to write to do stuff in slots which get called when signals are emitted. You probably ought slowly read through https://doc.qt.io/qt-5/signalsandslots.html, it's worth spending some time on this initially.

          How can a timers timeout slot get handled if something else is being processed. When does the event loop decide that its okay to process an event in between function calls?

          It doesn't work like this. The events/event loops are not being dealt with "between function calls". There are no interrupts going on in Qt. Think of it as the event loop is in charge and calling things:

          repeat
              process an event message in the queue, calling slots
          until something said to quit
          

          You can send your own event messages into the queue via emit of a signal, and the system is doing the same.

          If one of your slots takes a long time without exiting, the next message in the queue doesn't get processed.

          1 Reply Last reply
          3
          • P Offline
            P Offline
            pjorourke05
            wrote on last edited by pjorourke05
            #5

            @JonB Ok thanks.. that is where I was headed but didnt know if I was missing something because I am new to Qt.

            It seems like a good rule of thumb is to use signals and slots to connect the dots but if you have a long running operation than you need to use another thread.

            Also would this be a true statement. If you are currently executing a slot call it (slotA) and a timer times out which needs to invoke slotB. slotB will not be invoked until slotA is complete.. which means the way your application is designed could overlap execution with moment the timer's timeout slot (slotB) is suppose to execute meaning your timers timeout would not fire accurately. The way to avoid this is to use threads.

            JonBJ 1 Reply Last reply
            1
            • P pjorourke05

              @JonB Ok thanks.. that is where I was headed but didnt know if I was missing something because I am new to Qt.

              It seems like a good rule of thumb is to use signals and slots to connect the dots but if you have a long running operation than you need to use another thread.

              Also would this be a true statement. If you are currently executing a slot call it (slotA) and a timer times out which needs to invoke slotB. slotB will not be invoked until slotA is complete.. which means the way your application is designed could overlap execution with moment the timer's timeout slot (slotB) is suppose to execute meaning your timers timeout would not fire accurately. The way to avoid this is to use threads.

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

              @pjorourke05
              Yes.

              A time expiring event is just an event like all the others. It generates a message into the queue like everything else does, and that only gets processed (your slot gets called) when it's reached in the conceptual event loop above. Don't think of it as anything "interrupting" the code that's running. Yes, slotB won't get executed until slotA has exited.

              If you have a computation-heavy operation, or something which really must block/wait, you might put these in a separate thread. In particular, a separate thread from the main one servicing the GUI/timers, so that those continue to respond to the user in real time.

              1 Reply Last reply
              4

              • Login

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