I tried to reproduce OPs issue with my own MCVE (which is just a bit shorter).
#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.13.0
Start "worker 1"
This what OP observed. So, what?
- the
worker1.qThread.started
signal is connected to the worker2.start
slot
- the
worker1
is started
worker2
doesn't seem to start.
What made me suspicious: moveToThread()
.
The intention is to associate the Worker
object with its member QThread
.
What I'm not sure about: Is this possible before the QThread
is started?
To check this out, I commented the moveToThread()
:
Worker(const QString &name): name(name)
{
//moveToThread(&qThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
Output:
Qt Version: 5.13.0
Start "worker 1"
Start "worker 2"
The reason why I commented the moveToThread()
:
The call of qThread::start()
should happen in the context of the main application (thread).
So, moving worker2
to its QThread
means that the signal is sent to the event loop of worker2.qThread
– which is actually not yet started.
Hence, the event cannot be processed.
The moveToThread()
should be done later – e.g. in reaction of the started()
signal:
#include <QtWidgets>
struct Worker: QObject {
QString name;
QThread qThread;
Worker(const QString &name): name(name)
{
connect(&qThread, &QThread::started, this, &Worker::moveThisToThread);
connect(&qThread, &QThread::finished, this, &Worker::reportFinished);
}
void start()
{
qDebug() << "Start" << name;
qThread.start();
}
void moveThisToThread()
{
moveToThread(&qThread);
qDebug() << name << "associated to its thread, from now.";
}
void reportFinished()
{
qDebug() << "Exit" << name;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QCoreApplication app(argc, argv);
Worker worker1("worker 1");
Worker worker2("worker 2");
// install signal handlers
QObject::connect(&worker1.qThread, &QThread::started, &worker2, &Worker::start);
worker1.start();
// runtime loop
return app.exec();
}
Output:
Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
Start "worker 2"
"worker 2" associated to its thread, from now.
Bonus Question:
So does that mean "QThread::start" is useless as receiver of a signal?
No, it's not. Even if there is no existing signal with that signature (I know about) the application developer is free to “invent” one.
However, remembering that Qt5 doesn't actually require explicitly marked SLOT
s to use them for signals, a more obvious answer may be found in the past:
With Qt4 signals, the QThread::start
slot could have been connected to the QThread::started
signal directly. (The default value of the one and only parameter in QThread::start
becomes effective then.)
As I have no experience with Qt4 signals (I started with Qt5), I modified my sample code to prove me right:
QObject::connect(&worker1.qThread, SIGNAL(started()), &worker2.qThread, SLOT(start()));
Output:
Qt Version: 5.13.0
Start "worker 1"
"worker 1" associated to its thread, from now.
"worker 2" associated to its thread, from now.
The Start "worker 2"
isn't emitted anymore as worker1.started()
calls worker2.qThread.start()
directly, now.
So, with Qt4 signals the original code of OP might have been worked.
It wasn't the incompatibility of signal and slot (as somebody guessed) which caused the issue but probably the above described moveToThread()
issue (as well) which didn't make it work satisfyingly.