如果我不使用deletelater删除qthread会发生什么?

时间:2016-08-09 15:14:26

标签: qt signals-slots qthread

我正在尝试将Qthread与对象一起使用。为此,编写了这段代码:

QThread *thread1 = new QThread();
serialclass *obje = new serialclass();
void MainWindow::on_pushButton_baglan_clicked()
{
  obje->moveToThread(thread1);
  connect(thread1,SIGNAL(started()),obje,SLOT(baglan()), Qt::UniqueConnection);
  connect(obje,SIGNAL(finished()),thread1,SLOT(quit())); //end of the baglan function finished() signal is emitted.
  thread1->start();
}

我的代码有效。但我使用quit(),而不是deletelater()。按钮可以按下很长时间。第一个问题是,这种方法是真的吗?我的第二个问题是如果我按下按钮很多时候会发生什么。有很多线程吗?是每次创建一个线程吗?

1 个答案:

答案 0 :(得分:0)

这很好。您应该了解自己在做什么以及为什么:代码及其目的应来自您和理解。

当您按下按钮很多次时,应用程序可能处于以下两种状态之一:

  1. 线程已经完成:obje->thread() == nullptr并且您重新启动线程 - 它将正常工作。

  2. 该主题仍在运行:obje->thread() == thread1moveToThreadthread1->start()都不执行任何操作。

  3. 唉,停止线程没有意义。它有一个阻塞的事件循环,直到新事件到来,它不像空闲QThread正在耗尽任何CPU。启动一个线程很昂贵:它创建一个新的本机线程。完成的线程不再存在:是的,您仍然有一个QThread,但这就像拥有一个已关闭文件的句柄。毕竟,QThread是一个线程句柄。

    你应该按值而不是用指针来保持你的成员 - 这可以避免通过一个点对额外间接的愚蠢过早的悲观化。您可以提前设置所有连接。您不需要on_pushButton_baglan_clicked()插槽:您可以将按钮直接与SerialClass实例连接。您还应该使用一个安全可破坏的QThread派生类。

    您的代码可能如下所示。编译器将为您生成适当的资源释放析构函数。它是编译器的工作,在这项工作中它不会让你失败 - 而人类开发人员很容易失败。因此,你应该充分利用RAII,因为它会将一个卑微的手动作业转移到完美无缺的机器上。)

    // MyWindow.h
    #include <QMainWindow>
    #include <QThread>
    #include "SerialClass.h"
    #include "ui_MyWindow.h"
    
    class MyWindow : public QMainWindow {
      Q_OBJECT
      class SafeThread : public QThread {
        using QThread::run; // final
      public:
        ~SafeThread() { quit(); wait(); }
      } m_serialThread;
      SerialClass m_serial;
      Ui::MyWindow ui;
    public:
      MyWindow(QWidget * parent = nullptr);
    };
    
    // MyWindow.cpp
    #include "MyWindow.h"
    
    MyWindow::MyWindow(QWidget * parent) :
      QMainWindow{this}
    {
      ui.setupUi(this);
      connect(ui.pushButton_baglan, &QPushButton::clicked,
              &m_serial, &SerialClass::baglan);
      m_serial.moveToThread(&m_serialThread);
      m_serialThread.start();
    }
    

    如果您不希望所有实施细节都在MyWindow标题中,那么您should use a PIMPL