【问题标题】:Qt QThread stop when I needQt QThread 在我需要时停止
【发布时间】:2020-12-10 12:44:59
【问题描述】:
//Work.h
#ifndef WORK_H
#define WORK_H

#include <QDebug>
#include <QObject>
#include <QThread>

class Work : public QObject {
  Q_OBJECT
 public:
  explicit Work(QObject *parent = nullptr);

 public slots:
  void snap();
  void setStatus();

 signals:

 private:
  bool status;
};

#endif  // WORK_H


//Work.cpp
#include "Work.h"

Work::Work(QObject *parent) : QObject(parent) { status = true; }

void Work::snap() {
  status = true;
  while (true) {
    if (status) {
      qDebug() << "Work thread: " << QThread::currentThreadId();
    } else {
      qDebug() << "STOP";
      break;
    }
  }
}

void Work::setStatus() { status = false; }
//MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>

#include "Work.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
  Q_OBJECT

 public:
  MainWindow(QWidget *parent = nullptr);
  ~MainWindow();

 private:
  Ui::MainWindow *ui;
  Work *work;
  QThread thread;
};
#endif  // MAINWINDOW_H


//MainWindow.cpp
#include "MainWindow.h"

#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
  ui->setupUi(this);
  work = new Work();
  work->moveToThread(&thread);
  thread.start();

  connect(ui->startButton, SIGNAL(clicked()), work, SLOT(snap()));
  connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));
}

MainWindow::~MainWindow() {
  thread.terminate();
  delete ui;
}
//main.cpp
#include <QApplication>

#include "MainWindow.h"

int main(int argc, char *argv[]) {
  QApplication a(argc, argv);
  MainWindow w;
  qDebug() << QThread::currentThreadId();
  w.show();
  return a.exec();
}

我用MainWindow 显示,Work 做某事。我使用work-&gt;moveToThread(&amp;thread)

点击start按钮在Work中执行snap函数,我想做的是当我点击停止按钮时,snap函数输出STOP。我仍然可以随时startstop

但我失败了。在while loop 期间似乎无法更改状态。工作没有得到stopButton clicked signal。是因为优先吗?

谁能给我一些建议?

【问题讨论】:

标签: c++ qt


【解决方案1】:

首先考虑您的Work::snap 实现...

void Work::snap() {
  status = true;
  while (true) {
    if (status) {
      qDebug() << "Work thread: " << QThread::currentThreadId();
    } else {
      qDebug() << "STOP";
      break;
    }
  }
}

一旦启动,它就永远不会控制 Qt 事件循环。现在考虑connect 调用...

connect(ui->stopButton, SIGNAL(clicked()), work, SLOT(setStatus()));

由于ui-&gt;stopButtonwork 具有不同的线程亲缘关系,这实际上是一个排队连接,要求接收者有一个活动的事件循环。因此,对setStatus 的调用将永远处于等待状态。

实现目标的更好方法可能是使用简单的 atomic bool...

std::atomic<bool> status;

并更改 connect 调用以直接使用 lambda(未经测试)修改 status...

connect(ui->stopButton, &QPushButton::clicked, [this]{ work->setStatus(); });

【讨论】:

  • 我重试您的代码,但出现了一些错误:connect(ui-&gt;stopButton, &amp;QPushButton::clicked, [work]{ work-&gt;setStatus(); }); 我将其更改为:connect(ui-&gt;stopButton, &amp;QPushButton::clicked, [this] { work-&gt;setStatus(); });work 更改为this 后,您的答案是正确的。 link
  • @liuyulvv 确实,我的错误。感谢您的编辑。
【解决方案2】:

我解决了。

我在MainWindow 中添加一个槽和一个信号并更改stop 槽。

connect(ui->startButton, &QPushButton::clicked, this, &MainWindow::start);
connect(this, &MainWindow::startSnap, work, &Work::snap);

// start slot
void MainWindow::start() {
  thread.start();
  emit startSnap();
}

void MainWindow::stop() {
  if (thread.isRunning()) {
    thread.requestInterruption();
  }
}

并更改Work::snap中的代码

void Work::snap() {
  while (true) {
    if (QThread::currentThread()->isInterruptionRequested()) {
      qDebug() << "STOP";
      QThread::currentThread()->exit();
      return;
    } else {
      qDebug() << "Work thread: " << QThread::currentThreadId();
    }
  }
}

关键代码是:

  • thread.requestInterruption();(MainWindow::stop)
  • QThread::currentThread()-&gt;exit();(工作::snap)
  • thread.start();(MainWindow::start)

【讨论】:

  • 这与我自己的答案有何不同?您使用requestInterruption,而我使用原子布尔来请求中断。它应该等同于同一件事。你能说明如何调用MainWindow::stop 吗? connect 电话?
  • connect(ui-&gt;stopButton, &amp;QPushButton::clicked, this, &amp;MainWindow::stop);
猜你喜欢
  • 2017-07-29
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-01
  • 1970-01-01
  • 2013-04-21
相关资源
最近更新 更多