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.....
Forum Updated to NodeBB v4.3 + New Features

QTimer does not emit timeout.....

Scheduled Pinned Locked Moved Unsolved General and Desktop
15 Posts 3 Posters 11.8k 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.
  • Julian GuarinJ Offline
    Julian GuarinJ Offline
    Julian Guarin
    wrote on last edited by Julian Guarin
    #1

    Hello people.... I have:

     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();
    

    So t and this, live in the same thread... I've already checked. Also dotDisplay is declared as a slot.

    I've checked and the timer is running... by means of qDebug()<<t->remainingTime()

    Thing is, when timer reaches remaining time 0, the event loop won't trigger the signal... that's what I understand from the documentation.

    The thread, the slot's object and timer signal, are living at is the same.... as I've already pointed out.... what do you think I can do?

    Salutations.

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

      Julian GuarinJ 1 Reply Last reply
      0
      • VRoninV VRonin

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

        Julian GuarinJ Offline
        Julian GuarinJ Offline
        Julian Guarin
        wrote on last edited by Julian Guarin
        #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

          Julian GuarinJ 1 Reply Last reply
          0
          • VRoninV VRonin

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

            Julian GuarinJ Offline
            Julian GuarinJ Offline
            Julian Guarin
            wrote on last edited by Julian Guarin
            #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

              Julian GuarinJ 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?

                Julian GuarinJ Offline
                Julian GuarinJ Offline
                Julian Guarin
                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

                  Julian GuarinJ 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)?

                    Julian GuarinJ Offline
                    Julian GuarinJ Offline
                    Julian Guarin
                    wrote on last edited by Julian Guarin
                    #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

                      Julian GuarinJ 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);
                        
                        Julian GuarinJ Offline
                        Julian GuarinJ Offline
                        Julian Guarin
                        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