如何退出工作人员的事件循环QThread

时间:2016-06-10 18:33:56

标签: c++ qt qthread

我正在编写一个带有按钮的应用程序来启动/停止工作线程(实现QThread)。 工作线程每隔几毫秒就会调度一个作业。 为了终止工作线程,我从GUI线程调用worker.quit()worker.exit(0)也不起作用)方法并等待finished信号被触发。

问题在于,即使触发finished信号,线程也不会终止。

这是一个最小的例子: https://gist.github.com/NawfelBgh/941babdc011f07aa4ab61570d7b88f08

screenshot of the minimal example

修改

我对发生的事情的解释是错误的:工作线程被终止但是方法iter正在主线程中执行,正如@ sergey-tachenov所说的那样使用代码生成的日志记录:

void run() {
    std::cout <<"From worker thread: "<<QThread::currentThreadId() << std::endl;
...
void iter() {
    std::cout <<"From thread: "<<QThread::currentThreadId() << std::endl;
...
void MainWindow::on_pushButton_clicked()
{
    std::cout <<"From main thread: "<<QThread::currentThreadId() << std::endl;

我切换到不依赖QTimer的{​​{3}}。但我没有提交它作为答案,因为这个问题的标题是“如何退出工人QThread的事件循环”。

1 个答案:

答案 0 :(得分:4)

线程终止。只有你的计时器不在你已经启动但在主线程中的线程中运行,这就是它没有停止的原因。这是因为它默认使用排队连接,并且线程对象存在于创建它的线程中,这是主线程。解决它:

  • 子类QThread。除非您想要实际扩展QThread的功能,否则这通常是一个坏主意。
  • 创建一个继承QObject
  • 的单独工作对象
  • 使用moveToThread将worker对象移动到创建的线程。它将导致其所有插槽实际在线程中触发。如果您使用默认或排队连接,那就是。

The QThread docs提供了一个很好的例子(第一个)。

请注意,如果您确实想要使用线程提供的数据来更新GUI,则必须以某种方式正确地将该数据发布到GUI线程(可能使用emit和排队连接)而不是尝试直接从线程更新GUI。如果您想访问共享数据,您可能需要使用QMutex来保护它,而不是像使用共享计数器一样。