Home > front end >  QMetaObject::invokeMethod is not called in the correct thread
QMetaObject::invokeMethod is not called in the correct thread

Time:09-23

Given the following:

class MyThread : public QThread
{
      Q_OBJECT

   public:

      void run() override
      {
         qDebug() << "Started thread: " << QThread::currentThreadId();
         exec();
      }

   public slots:

      void someSlot()
      {
         qDebug() << "Slot called from thread: " << QThread::currentThreadId();
      }
};
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    qDebug() << "Main thread: " << QThread::currentThreadId();

    MyThread t;
    t.start();

    QMetaObject::invokeMethod(&t, "someSlot", Qt::QueuedConnection);

    return app.exec();
}

I will get the following output:

Main thread:  0x7fc24e2f3780
Started thread:  0x7fc245493700
Slot called from thread:  0x7fc24e2f3780

However, due to Qt::QueuedConnection & the event loop running in the instance of MyThread, I would expect the slot being executed in 0x7fc245493700.

What I am doing wrong?

CodePudding user response:

QThread objects lives in the main thread, i.e. the thread that created the object, not in the thread it represents. This is explicitly stated in the Qt doc (but follows the normal 'living'-rules) [1]:

It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). This means that all of QThread's queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.

Please check the QThread docs for an example of this worker-object approach.

Note that Qt::QueuedConnection is irrelevant, as it will be automatically queued when caller and slot lives in different threads[2]:

Qt::AutoConnection (Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.

  • Related