Search code examples
c++multithreadingqtqtimerqeventloop

QTimer->remainingTime() returns -1371648957


When I run the following code using Qt 5.3.2 the remaining time is set to -1371648957.

QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
timer->start(100);
qDebug() << "remaining" << timer->remainingTime();

If I continue to print the remaining time in a loop afterwards, the negative value just increases and therefore timeout() is never fired. This really makes no sense to me.

To give a bit of context, this code runs inside a separate thread and the QTimer is not created in the constructor of the threaded object.

Here is some updated code to make things clearer.

void MainObject::SomeMethod(){
    // main thread
    ObjectWithTimer *owt = new ObjectWithTimer();    
    QThread *someThread = new QThread();
    owt->moveToThread(someThread);
    connect(someThread, SIGNAL(started()), owt, SLOT(doStuff()));
    someThread->start();
}

void ObjectWithTimer::doStuff(){
    while(condition){
        // do various stuff
        // among other things emit SIGNALS to the main thread, that are received
        // so the event loop in the thread is running
        QTimer *timer = new QTimer(this);
        timer->setSingleShot(true);
        timer->start(100);
        qDebug() << "remaining" << timer->remainingTime();

        connect(timer, SIGNAL(timeout()), this, SLOT(onClientTimeoutTest()));
    }
}
void ObjectWithTimer::onClientTimeoutTest(){
    // this method is of course never fired, since the remaining time never reaches 0
}

I already checked that the timer creation runs correctly in the separate thread and that Qts event loop inside the thread is working, since I can emit signals that the main thread receives.

Also it makes not difference if I set the timer like this

timer->setSingleShot(true);
timer->setInterval(100);
timer->start();

If I change the number of seconds to 100000 or 0, the remaining time only slightly changes for example to -1374002988 which it does anyway when I restart the application, but the length remains the same.

Also I checked with the debugger on the timer->remainingTime() line and the internal inter variable is correctly set to 100.

Could this be a memory adress or something like that?


Solution

  • QTimer *timer = new QTimer(this);
    timer->setSingleShot(true);
    timer->start(100);
    qDebug() << "remaining" << timer->remainingTime();
    

    As QTimer works on an event loop, I suspect that calling remainingTime may return invalid at this point, as the Timer has not yet been fully initialised.

    If you follow the source code for QTimer, you'll see that it actually uses the timer of QObject and calls QObject::startTimer. The source for QObject (line 1632) shows that an event is dispatched at this point: -

    return d->threadData->eventDispatcher->registerTimer(interval, this);
    

    Therefore, allow the code to return to the main event loop after calling start and before requesting the remaining time.