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

标签 multithreading qt signals-slots

我试图更好地理解 Qt 信号和插槽与线程的结合。所以我尝试了这个最小的应用程序:

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

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;
}

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

最佳答案

QCoreApplication::quit ()未将其声明为线程安全方法,因此您不能从另一个线程调用它。您的应用程序可能会崩溃或出现未定义的行为 (UB)。
t.wait()永远不会返回,因为正在运行的线程一直在等待事件。要停止线程,您必须调用 QThread::quit () [slot]
如果您想在工作完成后退出应用程序,您必须发出一个连接到 QCoreApplication::quit () [static slot] 的信号。

如果你想在工作完成后停止工作线程,你还必须发出一个信号,连接到 void QThread::quit () [slot]
补充:Threads, Events and QObjects供进一步阅读

重要通知:您必须调用 QCoreApplication::exec()为了能够在线程之间使用信号和槽机制,排队连接。

来自 Qt QThread 文档:

Each QThread can have its own event loop. You can start the event loop by calling exec(); you can stop it by calling exit() or quit(). Having an event loop in a thread makes it possible to connect signals from other threads to slots in this thread, using a mechanism called queued connections. It also makes it possible to use classes that require the event loop, such as QTimer and QTcpSocket, in the thread. Note, however, that it is not possible to use any widget classes in the thread.



Qt::QueuedConnection 的文档:

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.

关于multithreading - Qt 线程在调用 exit/quit 后不会停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9358069/

相关文章:

java - 使用线程开发基于 Java 的聊天应用程序

c++ - 将一个对象的所有QT信号动态映射到一个插槽

python 在单击的 QTreeview 项目复选框上发出信号已更改

multithreading - Ccriticalsection 在生产中是否可用?

c# - 每次运行后 20 分钟运行线程

c - Glib:如何在另一个线程完成之前启动一个新线程?

qt - 为什么 QGroupBox 小部件不会随窗口的其余部分动态调整大小?

qt - 在 EGL 上渲染时的 OpenGL 撕裂效果

c++ - Qt 和 C++ - 未定义的插槽引用

qt - Qt:信号和插槽错误:未定义对`vtable的引用