I have a 3 QThreads invoking by one another (all inherited from QThread. I know some might suggest to use moveToThread, but just ignore this fact for now). The simplified code looks like following:
Thread1 class:
void
Thread1::run
{
// some execution
Thread2 t2 = new Thread2();
connect(t2,SIGNAL(finished),this,SLOT(onFinished));
t2->start();
while(!stop) // stop was initialized as false
{
this->msleep(10);
}
}
void Thread1::onFinished(){ stop = true; }
Thread2 class:
void
Thread2::run
{
// some execution
Thread3 t3 = new Thread3();
connect(t3,SIGNAL(finished),this,SLOT(onFinished));
t3->start();
while(!stop) // stop was initialized as false
{
this->msleep(10);
}
}
void Thread2::onFinished(){ stop = true; }
Thread3 class:
void
Thread3::run
{
// some execution
QMutexLocker ml(&mMutex);
}
When I have only two threads, it works perfectly fine (e.g. just thread2 and thread3). The onFinished() method seems not connecting with finished() signal properly anymore, after I moved to a three-threads scenario. The onFinished() in thread2 has ever been called. And I am pretty sure the execution of the thread3 has completed.
Can anybody tell me where I could have done wrong?
First of all you should note that the default connection type is Qt::AutoConnection
. This means if signal is emitted from a different thread than the receiving object's thread, Qt::QueuedConnection
is used. In this case: The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
So you need an event loop.
It works with 2 threads because you probably have an event loop running in your main thread. In your case where you use only thread2
and thread3
objects, thread2
object will actually live in the main thread, while thread3
object will live in the thread managed by the thread2
object. So slots in thread2
object should work.
But in the case of 3 threads, thread1
object would live in the main thread, thread2
object would live in the thread managed by thread1
object, and because there is no running event loop there, the slot in thread2
object will never be executed.
You can call QThread::exec() in your QThread::run()
function, but note that the slots will be executed in the thread where your QThread
object lives in, not the thread it manages. Because of this you shouldn't use slots in QThread
subclasses. You should create a QObject
subclass and move it to a thread.
Another option is to use Qt::DirectConnection
for the connection type, when you connect your signals to slots.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With