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
    #2

    do you have an event loop running in that thread (QThread::exec was 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

    ? 1 Reply Last reply
    0
    • VRoninV VRonin

      do you have an event loop running in that thread (QThread::exec was called)?

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

      @VRonin Yes. In fact the code posted is running inside that thread.

      The object where the code lives has been moved previously to the thread that this->thread() make reference.

      Uldfilterproject::Uldfilterproject(QObject* parent) : 
          QObject__(parent),
          m_pGrab(nullptr),
          net({"192.168.1.5",8989}),
          m_worker(new UldWorker())
      {
          
          /* Change worker threads */
          m_worker->moveToThread(&m_thread);
      
          /* Now Connect signals, with a queue: why? this object and m_worker live in different threads now :) */
          connect(this,&Uldfilterproject::awakeWorker,m_worker,&UldWorker::uploadStart_WORKER,Qt::QueuedConnection);
          
          /*Start the thread */    
          m_thread.start();
          
          /* Start */
          emit awakeWorker(net.m_hostName,net.m_port);
      

      The uploadStart_WORKER slot is queued executed when I emit awakeWorker.... inside that slot I ran:

      void UldWorker::uploadStart_WORKER(QString hostName, quint16 portNumber){
       QTimer * t = new QTimer(this);
          
          /* Timer dot */
          connect(t,SIGNAL(timeout()),this,SLOT(dotDisplay()));
          t->start(10000);
          
          qDebug()<<"t thread is:     "<<t->thread();
          qDebug()<<"this thread is:  "<<this->thread();
      
      1 Reply Last reply
      0
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #4

        Can you post the code around where you create the object referenced by this?

        "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

          Can you post the code around where you create the object referenced by this?

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

          @VRonin I did it.... please check the previous post as it is edited.

          1 Reply Last reply
          0
          • 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