我试图更好地理解 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/