调用exit/quit后Qt线程不会停止

Ele*_*ito 5 qt multithreading signals-slots

我正在尝试与线程一起更好地理解Qt信号和插槽.所以我尝试了这个最小的应用:

foo.h中:

#include <QObject>

class A : public QObject {
  Q_OBJECT

public:
  void doit();

signals:
  void x();
};

class B : public QObject {
  Q_OBJECT

public slots:
  void h();
};
Run Code Online (Sandbox Code Playgroud)

Foo.cpp中:

#include "foo.h"

#include <QThread>
#include <QCoreApplication>

void B::h() {
  qDebug("[%d] B::h() here!", (int) QThread::currentThreadId());
  QCoreApplication::instance()->quit();
}

void A::doit() {
  qDebug("[%d] emitting...", (int) QThread::currentThreadId());
  emit x();
}

int main(int argc, char* argv[]) {
  QCoreApplication app(argc, argv);
  A a;
  B b;
  QObject::connect(&a, SIGNAL(x()), &b, SLOT(h()));
  QThread t;
  t.start();
  b.moveToThread(&t);
  a.doit();
  t.wait();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

一切都很好,只有最后的t.wait()永远不会返回.我的理解是调用quit()应该停止事件循环,这意味着exec()应该返回,所以应该run()并且线程执行应该停止.我错过了什么吗?

Dmi*_*riy 10

QCoreApplication::quit ()未声明为线程安全方法,因此您无法从另一个线程调用它.您的应用程序可能崩溃或获得未定义的行为(UB).

t.wait()将永远不会返回,因为正在运行的线程一直在等待事件.要停止线程,您必须调用QThread::quit () [slot]

如果要在完成工作后退出应用程序,则必须发出连接到的信号 QCoreApplication::quit () [static slot]

如果要在工作完成后停止工作线程,还必须发出连接到的信号 void QThread::quit () [slot]

添加:线程,事件和QObject以供进一步阅读

重要提示:您必须调用QCoreApplication::exec()才能在线程,排队连接之间使用信号和插槽机制.

来自Qt QThread doc:

每个QThread都有自己的事件循环.您可以通过调用exec()来启动事件循环; 你可以通过调用exit()或quit()来停止它.在线程中具有事件循环使得可以使用称为排队连接的机制将来自其他线程的信号连接到该线程中的槽.它还可以在线程中使用需要事件循环的类,例如QTimer和QTcpSocket.但请注意,无法在线程中使用任何窗口小部件类.

Doc for Qt :: QueuedConnection:

当控制返回到接收者线程的事件循环时,将调用该槽.插槽在接收器的线程中执行.