7
votes

I'm trying to run a method on the GUI thread using QMetaObject::invokeMethod, which returns true. But, if I use Qt::QueuedConnection my method never gets called (even if invokeMethod returns true).

This is what I'm using:

QMetaObject::invokeMethod(this, "draw_widgets", Qt::QueuedConnection)

I don't get any error messages or anything... If I use Qt::AutoConnection or Qt::DirectConnection the method does get called, but from the same thread of course. Not from the GUI thread, which is what I need.

draw_widgets is a public slot of type void draw_widgets() and my class inherits QObject and uses the Q_OBJECT macro as well.

I would appreciate any help on this, or on how to check why the method is not being called.

Thanks.

1
I have a similar situation: I have a class that inherits from QObject and uses Q_OBJECT. The instance of this class is created in the main loop. Then, while executing a method of the same class in the main loop, I call QMetaObject::invokeMethod(this, "hideListsSlot", Qt::QueuedConnection);, where void hideListsSlot() is a public slot of the class. The slot is never invoked.Giorgio

1 Answers

11
votes

The "true" is telling you the message was successfully queued. That doesn't mean the queued message was ever processed...

Let us say your program has 10 threads (Thread1-Thread10). You queue a message from Thread7. Which thread will it be queued to? And when will items on this queue be processed?

The answer is that every QObject has something called Thread Affinity, and this is the thread where a queued slot will be run. The default affinity is to the thread where the object was created (but you can change it with QObject::moveToThread().)

If you want to queue something to the GUI thread, then the object specified by your this pointer should have the GUI thread's affinity. You can check this with the QObject::thread() method.

But in any case, no matter what thread you queue to... you must have some kind of message pump running on that thread. Look at for instance QThread::exec(). If your thread affinity is to the GUI then presumably this is already the case because you are running the app's exec.

(As a sidenote, direct calls to QMetaObject::invokeMethod are usually unnecessary. You can create a signal and tie it to a slot, then emit the signal in lieu of the invoke.)