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. QTimer does not emit timeout.....
Qt 6.11 is out! See what's new in the release blog

QTimer does not emit timeout.....

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 3 Posters 13.6k 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.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #6

    Yes, sorry you anticipated me with the edit. What's the type of m_thread? can you use Qt5 connection for QTimer too?

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    ? 1 Reply Last reply
    0
    • VRoninV VRonin

      Yes, sorry you anticipated me with the edit. What's the type of m_thread? can you use Qt5 connection for QTimer too?

      ? Offline
      ? Offline
      A Former User
      wrote on last edited by
      #7

      @VRonin The m_thread object is a Qt's QThread.

      1 Reply Last reply
      0
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #8

        did you try Qt5 connection on the timer? (or in other words are you sure dotDisplay is declared as slot)?

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        ? 1 Reply Last reply
        0
        • VRoninV VRonin

          did you try Qt5 connection on the timer? (or in other words are you sure dotDisplay is declared as slot)?

          ? Offline
          ? Offline
          A Former User
          wrote on last edited by A Former User
          #9

          @VRonin Indeed:

          
          
          class UldWorker:public QObject{
              Q_OBJECT
          public:
              UldWorker(QObject * parent = 0);
              ~UldWorker(){}
          
          public slots:
              void uploadStart_WORKER(QString hostName, quint16 portNumber);
          private slots:
              void dotDisplay();
          private:
          
          };
          

          However I guess I'm doing something awfully wrong.....

          My UldWorker object is as well as the timer in the same thread:

          0_1474038654008_upload-01cf7f6e-1586-4aa1-8d38-f41f046164ed

          http://doc.qt.io/qt-4.8/images/threadsandobjects.png

          Let's suppose Obj5 is my UldWorker and Obj6 is my timer. They are indeed in the same Thread. So signal and slot connection can be done directly.

          But according to documentation:

          In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timers thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread."
          http://doc.qt.io/qt-5/qtimer.html
          

          I'm sure the new thread was started by means of QThread:exec(), why because I called m_thread.start()and according to docs:

          void QThread::start(Priority priority = InheritPriority)
          
          Begins execution of the thread by calling run(). The operating system will schedule the thread according to the priority parameter. If the thread is already running, this function does nothing.
          
          void QThread::run()
          
          The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec().
          
          
          
          http://doc.qt.io/qt-5/qthread.html
          

          As m_thread is basically a non reimplemented QThread class..... It is a QThread.... the default implementation of run, is called when I did m_thread.start() , so exec() was called. The event loop was initiated.

          This is the whole implementation of the slot which runs in the new thread:

          void UldWorker::uploadStart_WORKER(QString hostName, quint16 portNumber){
              
          
              qDebug()<<"Connection Manager Thread";
              
              QTimer * t = new QTimer(this);
              QTcpSocket * s = new QTcpSocket();
              QTimer * t = new QTimer(this);
              
              /* Error Handling */
              typedef void(QAbstractSocket::*QAbstractSocketError)(QAbstractSocket::SocketError);
              connect(s,static_cast<QAbstractSocketError>(&QAbstractSocket::error),this,&UldWorker::errorNotify);
              
              /* State changed */
              connect(s,&QAbstractSocket::stateChanged,this,&UldWorker::socketStateDisplay);
              
              /* Timer dot */
              connect(t,SIGNAL(timeout()),this,SLOT(dotDisplay()));
              t->start(10000);
              
              qDebug()<<"t thread is:     "<<t->thread();
              qDebug()<<"this thread is:  "<<this->thread();
              while (m_alive){
                  QAbstractSocket::SocketState ss;
                  ss = s->state();
                  if (!m_qi.isEmpty()){
                      /* Si hay al menos una imagen */
                      if (ss == QAbstractSocket::UnconnectedState){
                          /* Si no está conectado el socket Conectarse */
                          //qDebug()<<"Attempting Connection";
                          s->connectToHost(hostName,portNumber);
                          s->waitForConnected();
                          //t->setInterval(1000);
                          //t->setSingleShot(false);
                          qDebug()<<t->remainingTime();
                          continue;
                          
                      } else if (ss == QAbstractSocket::ConnectingState){
                      } else if (ss == QAbstractSocket::ConnectedState){
                          /* Stop pending connection timer */                
                          t->stop();
                          
                          
                          /* Si el socket está conectado, enviar la información */
                          /* pop from q and sent Information */
                          QImage i = m_qi.dequeue();
                          continue;
                      } else {
                          /* Socket is doing whatever I don't care */
                          continue;
                      }
                      
                  } else {
                      
                      if (s->state() == QAbstractSocket::ConnectedState){
                          /* So there's no workload, free connection */ 
                          s->disconnectFromHost();    
                          continue;
                      }
                  }
              }
              
              s->disconnectFromHost();
              delete s;
          
          }
          
          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by VRonin
            #10

            you are defining QTimer * t = new QTimer(this); twice

            could you try and change

            connect(t,SIGNAL(timeout()),this,SLOT(dotDisplay()));
                t->start(10000);
            

            into

            connect(t,&QTimer::timeout,this,&UldWorker::dotDisplay);
            t->setInterval(10000);
            QMetaObject::invokeMethod(t, "start",Qt::QueuedConnection);
            

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            ? 1 Reply Last reply
            1
            • VRoninV VRonin

              you are defining QTimer * t = new QTimer(this); twice

              could you try and change

              connect(t,SIGNAL(timeout()),this,SLOT(dotDisplay()));
                  t->start(10000);
              

              into

              connect(t,&QTimer::timeout,this,&UldWorker::dotDisplay);
              t->setInterval(10000);
              QMetaObject::invokeMethod(t, "start",Qt::QueuedConnection);
              
              ? Offline
              ? Offline
              A Former User
              wrote on last edited by
              #11

              @VRonin Thank you. Well timer is running, i did this:

              void UldWorker::uploadStart_WORKER(QString hostName, quint16 portNumber){
                  
                  qDebug()<<"Connection Manager Thread";
                  m_alive = true;
                  
                  QTcpSocket * s = new QTcpSocket();
                  
                  /* Error Handling */
                  typedef void(QAbstractSocket::*QAbstractSocketError)(QAbstractSocket::SocketError);
                  connect(s,static_cast<QAbstractSocketError>(&QAbstractSocket::error),this,&UldWorker::errorNotify);
                  
                  /* State changed */
                  connect(s,&QAbstractSocket::stateChanged,this,&UldWorker::socketStateDisplay);
                  
                  /* Timer dot */
                  connect(t,SIGNAL(timeout()),this,SLOT(dotDisplay()));
                  t->start(10000);
                  qDebug()<<"Metatest:"<<QMetaObject::invokeMethod(t,"timeout",Qt::AutoConnection);
                  qDebug()<<"t thread is:     "<<t->thread();
                  qDebug()<<"this thread is:  "<<this->thread();
                  while (m_alive){
                      QAbstractSocket::SocketState ss;
                      ss = s->state();
                      if (!m_qi.isEmpty()){
                          /* Si hay al menos una imagen */
                          if (ss == QAbstractSocket::UnconnectedState){
                              /* Si no está conectado el socket Conectarse */
                              //qDebug()<<"Attempting Connection";
                              s->connectToHost(hostName,portNumber);
                              //s->waitForConnected();
                              //t->setInterval(1000);
                              //t->setSingleShot(false);
                              qDebug()<<t->remainingTime();
                              continue;
                              
                          } else if (ss == QAbstractSocket::ConnectingState){
                              if (!t->remainingTime()){
                                  dotDisplay();
                                  t->start(10000);
                              }
                          } else if (ss == QAbstractSocket::ConnectedState){
                              /* Stop pending connection timer */                
                              t->stop();
                              
                              
                              /* Si el socket está conectado, enviar la información */
                              /* pop from q and sent Information */
                              QImage i = m_qi.dequeue();
                              continue;
                          } else {
                              /* Socket is doing whatever I don't care */
                              continue;
                          }
                          
                      } else {
                          
                          if (s->state() == QAbstractSocket::ConnectedState){
                              /* So there's no workload, free connection */ 
                              s->disconnectFromHost();    
                              continue;
                          }
                      }
                  }
                  
                  s->disconnectFromHost();
                  delete s;
              
              }
              

              So in the part

              if (ss == QAbstractSocket::UnconnectedState){
                              /* Si no está conectado el socket Conectarse */
                              //qDebug()<<"Attempting Connection";
                              s->connectToHost(hostName,portNumber);
                              //s->waitForConnected();
                              //t->setInterval(1000);
                              //t->setSingleShot(false);
                              qDebug()<<t->remainingTime();
                              continue;
                              
                          } else if (ss == QAbstractSocket::ConnectingState){
                              if (!t->remainingTime()){
                                  dotDisplay();
                                  t->start(10000);
                              }
                          } else if (ss == QAbstractSocket::ConnectedState){
                              /* Stop pending connection timer */                
                              t->stop();
                              
                              
                              /* Si el socket está conectado, enviar la información */
                              /* pop from q and sent Information */
                              QImage i = m_qi.dequeue();
                              continue;
                          } else {
                              /* Socket is doing whatever I don't care */
                              continue;
                          }
              

              When in ConnectingState, I checked if the timer is done, and manually call the slot. That's how I know the timer is running and behaves as much as I want. I follow your suggestion of invoking, but rather than invoke the start signal of the timer I did it with the timeout one, and indeed the slot was called.. I used an AutoConnection because timer and this object (uldworker), both live and operate in the same thread.

              So this way it behaves as needed... Im making a "dot waiting for connection" for debugging purposes (all this for debugging sake).
              I'd like that it works by triggering automatically the dotDisplay slot, but seems I have tho check this manually.


              After that I also made what you suggest, of testing start slot, and it returned true.... So I think the case for nonrunning timer is that timer is running.

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by VRonin
                #12

                Ok, found the issue here, the problem is with while (m_alive) if the loops keep running the thread event loop will never have the chance to trigger slots from signals. You can fix it either by changing design (make it asynchronous) or adding QCoreApplication::processEvents just below the while

                while (m_alive){
                QCoreApplication::processEvents();
                // the rest
                

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                C 1 Reply Last reply
                2
                • VRoninV VRonin

                  Ok, found the issue here, the problem is with while (m_alive) if the loops keep running the thread event loop will never have the chance to trigger slots from signals. You can fix it either by changing design (make it asynchronous) or adding QCoreApplication::processEvents just below the while

                  while (m_alive){
                  QCoreApplication::processEvents();
                  // the rest
                  
                  C Offline
                  C Offline
                  cscsaba4
                  wrote on last edited by cscsaba4
                  #13

                  @VRonin Could you suggest any good practice to replace a while loop? In my case, I start a thread by moving my QObject into a QThread instance. The worker only has a single-shooting timer and a while loop that checks a given requirement as long as the timer is running (termination condition). If the condition is true, the timer is stopped, thus preventing timer firing and calling the connected slot.
                  Until I read your comment I had the same problem as OP. Adding QCoreApplication::processEvents below while solved my problem, but I'm curious, which one of your suggested solutions is the better practice and how could the while loop be replaced.

                  class Worker(QObject):
                      finished = pyqtSignal()
                      error = pyqtSignal()
                  
                      def __init__(self, port, parent=None):
                          super(Worker, self).__init__(parent)
                          self.port = port
                          self.portData = port.portData
                          self.getPosition = port.getPosition
                  
                      def process(self):
                          timer = QTimer(self)
                          timer.setSingleShot(True)
                          timer.timeout.connect(self.portData.sender.pulseSignal)
                          timer.timeout.connect(self.printFiring)
                  
                          timer.start(self.portData.retention)
                          while timer.isActive():
                              position = self.getPosition()
                              if position < self.portData.start or position > (self.portData.start + self.portData.window):
                                  self.timer.stop()
                          self.finished.emit()
                  
                      def printFiring(self):
                          print("timer fired")
                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #14

                    move the check to a different method

                    I'll try to write python but I'm not proficient with the language.

                    class Worker(QObject):
                        finished = pyqtSignal()
                        error = pyqtSignal()
                        def __init__(self, port, parent=None):
                            super(Worker, self).__init__(parent)
                            self.port = port
                            self.portData = port.portData
                            self.getPosition = port.getPosition
                            self.timeoutTimer = QTimer(self)
                            self.timeoutTimer.setSingleShot(True)
                            self.timeoutTimer.timeout.connect(self.positionFinished)
                            self.checkTimer = QTimer(self)
                            self.checkTimer.setSingleShot(False)
                            self.checkTimer.timeout.connect(self.checkPosition)
                        def process(self):
                            self.checkTimer.start(100)
                            self.timeoutTimer.start(self.portData.retention)
                        def checkPosition(self):
                            position = self.getPosition()
                            if position < self.portData.start or position > (self.portData.start + self.portData.window):
                                positionFinished()
                        def positionFinished(self):
                            self.checkTimer.stop()
                            self.timeoutTimer.stop()
                            self.portData.sender.pulseSignal()
                            self.printFiring()
                            self.finished.emit()
                        def printFiring(self):
                            print("timer fired")
                    

                    checkTimer will check 10 times per second the position while timeoutTimer holds a process timeout. Whenever the position condition is satisfied or the maximum timeout is reached positionFinished is called

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    C 1 Reply Last reply
                    2
                    • VRoninV VRonin

                      move the check to a different method

                      I'll try to write python but I'm not proficient with the language.

                      class Worker(QObject):
                          finished = pyqtSignal()
                          error = pyqtSignal()
                          def __init__(self, port, parent=None):
                              super(Worker, self).__init__(parent)
                              self.port = port
                              self.portData = port.portData
                              self.getPosition = port.getPosition
                              self.timeoutTimer = QTimer(self)
                              self.timeoutTimer.setSingleShot(True)
                              self.timeoutTimer.timeout.connect(self.positionFinished)
                              self.checkTimer = QTimer(self)
                              self.checkTimer.setSingleShot(False)
                              self.checkTimer.timeout.connect(self.checkPosition)
                          def process(self):
                              self.checkTimer.start(100)
                              self.timeoutTimer.start(self.portData.retention)
                          def checkPosition(self):
                              position = self.getPosition()
                              if position < self.portData.start or position > (self.portData.start + self.portData.window):
                                  positionFinished()
                          def positionFinished(self):
                              self.checkTimer.stop()
                              self.timeoutTimer.stop()
                              self.portData.sender.pulseSignal()
                              self.printFiring()
                              self.finished.emit()
                          def printFiring(self):
                              print("timer fired")
                      

                      checkTimer will check 10 times per second the position while timeoutTimer holds a process timeout. Whenever the position condition is satisfied or the maximum timeout is reached positionFinished is called

                      C Offline
                      C Offline
                      cscsaba4
                      wrote on last edited by
                      #15

                      @VRonin That's a very nice idea, thank you for your reply!

                      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