QTimer does not emit timeout.....



  • 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.



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



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


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



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



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



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



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



  • @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;
    
    }
    


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


  • @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.



  • 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
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.