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 ofQThread
'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.