如何在Qt中通知另一个线程中的插槽

How to signal a slot in another thread in Qt

本文关键字:线程 插槽 另一个 通知 Qt      更新时间:2023-10-16

我用Qt写了一个简单的信号槽应用程序,我想发送一个信号给另一个线程,它运行在主线程之外。

下面是我的代码:
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();
};

但是它返回:

0x7f9851c988c0
0x7f9851c988c0

如何调用输出另一个threadID的信号?

你搞反了。QThread是一个线程句柄,而不是线程本身。如果您想在另一个线程中运行某些东西,它属于您移动到线程的普通QObject。你根本不需要从QThread中推导!您也不应该将QThread的基础QObject移动到线程本身。你所做的就是在线程本身中有一个线程的句柄。一旦线程完成,句柄变为非功能(QObject与空thread())。

首先,如果所有你需要的是运行一些代码,运行到完成(例如做一个计算)在一个工作线程,使用线程池和QtConcurrent框架。它为你管理所有的线程:

#include <QtConcurrent>
...
QThread::currentThread()->setObjectName("main");
qDebug() << QThread::currentThread();
QtConcurrent::run([]{ qDebug() << QThread::currentThread(); }

如果你坚持自己控制线程的生命周期,你可以这样做:

#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();
}

最后,注意QDebug类知道如何在传递指向QObject的指针时输出对象的地址、类和名称(如果设置了)。因此,您不需要使用QThread::currentThreadId(), QThread::currentThread()就足够了—您可以为线程提供助记名称,因为它们毕竟是QObject

按如下方式实现Thread1构造函数:

Thread1(QObject* parent) { moveToThread(this); }