当类暴露给QML时,如何正确地停止类中的线程

时间:2014-02-17 15:18:53

标签: multithreading qt qml signals-slots

我有一个暴露于QML的课程:

qmlRegisterType(“SerialThread”,1,0,“SerialThread”);

该类继承QThread,QThread.start()从QML调用。

当用户关闭应用程序时,如何在程序终止之前正确退出线程?

2 个答案:

答案 0 :(得分:3)

在析构函数中,您应该调用quit(),然后调用wait()。因为,希望你已经让QML拥有了线程对象,它会破坏它 - 随意验证析构函数实际上已被执行。

如果你没有在线程中旋转事件循环,那么你必须重新实现quit()来设置你自己的停止标志。由于您隐藏了基础非虚拟quit(),因此您的“线程”不再是QThread,并且您必须私下继承QThread - 这是一个否则会出现语义错误(并导致错误)。

如何发生此类错误?既然你可以在一个QThread的某个地方传递你的“不完全”的线程,那么它的那些用户可以自由地认为它是一个真正的线程,而不是“不是一个”,并调用QThread::quit()方法,这是一个没有事件循环的无操作。因此错误。

要维护LSP,如果需要覆盖非虚拟公共方法,则必须私有地从父类继承,因为它在父级可用的地方不可用。

class MyThread : private QThread {
  Q_OBJECT
  Q_DISABLE_COPY(MyThread)
  volatile bool m_stop;
  void run() { ... }
public:
  MyThread(QObject * parent = nullptr) : QThread(parent) { ... }
  void quit() { m_stop = true; }
  // It's important to fully qualify the Priority type, otherwise moc will generate
  // wrong code.
  Q_SLOT void start(QThread::Priority priority = InheritPriority) {
    if (isRunning()) return;
    m_stop = false;
    QThread::start();
  }
  using QThread::isRunning;
  using QThread::isFinished;
  bool isInterruptionRequested() const { return m_stop; }
  ~MyThread() {
    quit();
    wait();
  }
  // Publicly we're only a QObject, not a thread
  operator QObject&() { return *this; }
  operator const QObject&() const { return *this; }
  void run() {
    while (!m_stop) { ... }
  }
};

答案 1 :(得分:0)

你可以在main中返回退出值之前调用thread.stop()并检查thread.is Running()。