I have written a simple signal slot application using Qt. I want to send a signal to another thread that is runs out of the main thread.
Here is my code:
class Thread1 : public QThread
{
Q_OBJECT
void run()
{
exec();
}
public:
Thread1(QObject* parent);
public slots:
void a()
{
qInfo()<<QThread::currentThreadId();
}
};
class Object : public QObject
{
Q_OBJECT
public:
Object(){}
void start()
{
qInfo()<<QThread::currentThreadId();
Thread1* thread = new Thread1(this);
connect(this,SIGNAL(a()),thread,SLOT(a()));
thread->start();
emit a();
}
signals:
void a();
};
But it returns:
0x7f9851c988c0
0x7f9851c988c0
How can I call a signal that outputs another threadID?
You've got it backwards. A QThread
is a thread handle, not a thread itself. If you want to run something in another thread, it belongs in a plain QObject
that you move to a thread. You don't need to derive from QThread
at all! You also shouldn't move a QThread
's base QObject
to the thread itself. What you do is have a handle to the thread live in the thread itself. As soon as the thread finishes, the handle becomes non-functional (a QObject
with a null thread()
).
First of all, if all you need is to run some code that runs to completion (e.g. does a calculation) in a worker thread, use the thread pool and QtConcurrent
framework. It manages all the threads for you:
#include <QtConcurrent>
...
QThread::currentThread()->setObjectName("main");
qDebug() << QThread::currentThread();
QtConcurrent::run([]{ qDebug() << QThread::currentThread(); }
If you insist on controlling the thread's lifetime yourself, you'd do the following:
#include <QtCore>
struct Worker : QObject {
Q_SLOT void aSlot() {
qDebug() << QThread::currentThread();
QThread::currentThread()->quit();
}
Q_SIGNAL void aSignal();
Q_OBJECT
};
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QThread::currentThread()->setObjectName("main");
QThread thread;
thread.setObjectName("thread");
Worker a, b;
b.moveToThread(&thread);
thread.start();
QObject::connect(&a, &Worker::aSignal, &b, &Worker::aSlot);
emit a.aSignal(); // the signal is emitted from the main thread
thread.wait();
}
Finally, note that the QDebug
class knows how to output the object's address, class and name (if set) when passed a pointer to a QObject
. Thus, you don't need to use QThread::currentThreadId()
, the QThread::currentThread()
is sufficient - and you can give the threads mnemonic names since they are QObject
s, after all.
Implement Thread1
constructor like following :
Thread1(QObject* parent) { moveToThread(this); }