首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt线程在调用exit/quit后不停止

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

Stack Overflow用户
提问于 2012-02-20 16:26:02
回答 2查看 13K关注 0票数 5

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

foo.h:

代码语言:javascript
复制
#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:

代码语言:javascript
复制
#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()应该返回,所以应该运行(),线程执行应该停止。我是不是遗漏了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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的单据:

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

票数 11
EN

Stack Overflow用户

发布于 2012-02-20 17:19:38

看起来你的代码有很多地方出了问题。

  • ,你不能叫app.exec()。这意味着没有主事件循环。Ax信号不会发出。默认情况下
  • ,Qt中的线程has it's own even loop (至少从几年开始)。然后启动一个调用Qthread::run()的线程,并启动事件循环。这就是你的线程所在的地方,而不是t.wait()的用途是在t.wait().
  • What中?我相信你误用了它。
  • (如果其他一切都正常的话),在B::h()中,您将从另一个线程停止主线程。这就是你想做的吗?

因此,我的第一个建议是添加app.exec(),看看它是如何运行的。解释你正在尝试做什么,然后重写一些其他的东西。因为you're doing it wrong

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9358069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档