PDA

View Full Version : QTimer::singleShot(0, ... confusion



bjoern83
19th April 2010, 12:53
Hi,

I'm a little bit confused about the usage of


QTimer::singleShot(0, this, SLOT(doSomething()));

The document states that "a QTimer with a timeout of 0 will time out as soon as all the events in the window system's event queue have been processed". So does this mean that it is essentially the same as


QMetaObject::invokeMethod(this, "doSomething", Qt::QueuedConnection);

or does it mean that in the case of an currently empty event queue the slot will be called directly?

wysota
19th April 2010, 13:03
The two calls are essientially the same. There is a tiny technical difference but it doesn't influence the final effect.

aamer4yu
19th April 2010, 13:22
Every system has a event loop where events are processed. Say like
application::processEvents()
{
// process event list..
}


QTimer::singleShot(0, this, SLOT(doSomething()));
Now the place where you write the above statement is inside some processing event.
When this loop is done, processEvents will be called again and in that the doSomething() will be executed.

So this is like calling doSomething in the next event loop, rather than calling it immediately.
Hope you get the idea.

wysota
19th April 2010, 13:40
So this is like calling doSomething in the next event loop, rather than calling it immediately.

So is the other call... The technical difference is the order of calls. Timers are checked after all events are processed, so if you have such code:

class Object : public QObject {
Q_OBJECT
public slots:
void funcA() { qDebug() << Q_FUNC_INFO; }
void funcB() { qDebug() << Q_FUNC_INFO; }
};

and you do this:

Object *o = new Object;
QMetaObject::invokeMethod(o, "funcA", Qt::QueuedConnection);
QMetaObject::invokeMethod(o, "funcB", Qt::QueuedConnection);
Then you should get:

Object::funcA()
Object::funcB()

But if you do:

Object *o = new Object;
QTimer::singleShot(0, o, SLOT(funcA()));
QMetaObject::invokeMethod(o, "funcB", Qt::QueuedConnection);

you will probably get:

Object::funcB()
Object::funcA()


I haven't verified that but that's what I would be expecting to see.

bjoern83
19th April 2010, 14:45
Thanks a lot for the answers! Basically, that was my assumption as well, but I ran into a problem in my code using the mac cocoa port of qt that - at least as I see it - can only be caused if under some conditions QTimer::singleShot(0, ...) is called directly. Then I browsed a little bit through the qt sources and found out that there are some calls to QTimer::singleShot with a msecs value of 1, which to me doesn't make much sense because of the timer resolution on most platforms. And that there a more calls to QMetaObject::invokeMethod(..., Qt::QueuedConnection) than to QTimer::singleShot(0, ...)
After that I checked the QTimer documentation and found it a little bit hooey on that matter, but maybe I just missed the keyword "queued" in it to make things clearer.

lanmanck
9th October 2022, 11:30
I think it jusk like:
CallInUiThreadLater(yourSlotFunction);