我试图更好地理解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();
};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()应该返回,所以应该运行(),线程执行应该停止。我是不是遗漏了什么?
发布于 2012-02-20 17:34:32
QCoreApplication::quit ()没有声明为线程安全方法,所以您不能从另一个线程调用它。您的应用程序可能会崩溃或获得未定义的行为(UB)。
t.wait()永远不会返回,因为正在运行的线程一直在等待事件。要停止线程,必须调用QThread::quit () [slot]
如果您想在完成工作后退出应用程序,则必须发出一个连接到QCoreApplication::quit () [static slot]的信号
如果想要在工作完成后停止工作线程,还必须发出一个连接到void QThread::quit () [slot]的信号
添加:Threads, Events and QObjects以供进一步阅读
重要提示:你必须调用QCoreApplication::exec()才能在线程、队列连接之间使用信号和槽机制。
来自Qt QThread文档:
每个QThread都可以有自己的事件循环。您可以通过调用exec()来启动事件循环,也可以通过调用exit()或quit()来停止它。在线程中有一个事件循环使得可以使用一种称为queued connections的机制将来自其他线程的信号连接到该线程中的槽。它还可以在线程中使用需要事件循环的类,如QTimer和QTcpSocket。但是,请注意,不能在线程中使用任何小部件类。
Qt::QueuedConnection的单据:
当控制返回到接收方线程的事件循环时,将调用插槽。该槽在接收器的线程中执行。
发布于 2012-02-20 17:19:38
看起来你的代码有很多地方出了问题。
,
app.exec()。这意味着没有主事件循环。A的x信号不会发出。默认情况下Qthread::run()的线程,并启动事件循环。这就是你的线程所在的地方,而不是t.wait()的用途是在t.wait().B::h()中,您将从另一个线程停止主线程。这就是你想做的吗?因此,我的第一个建议是添加app.exec(),看看它是如何运行的。解释你正在尝试做什么,然后重写一些其他的东西。因为you're doing it wrong
https://stackoverflow.com/questions/9358069
复制相似问题