【问题标题】:what happens if i don't use deletelater for deleting qthread?如果我不使用 deletelater 来删除 qthread,会发生什么?
【发布时间】:2016-08-09 15:14:26
【问题描述】:

我正在尝试将 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(),而不是deleter()。按钮可以按下很多时间。第一个问题是,这种方法是真的吗?我的第二个问题是如果我长时间按下按钮会发生什么。有很多线程吗?每次都创建一个线程吗?

【问题讨论】:

    标签: qt signals-slots qthread


    【解决方案1】:

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

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

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

    2. 线程仍在运行:obje->thread() == thread1moveToThreadthread1->start() 均不执行任何操作。

    唉,停止线程是没有意义的。它有一个事件循环,在新事件到达之前被阻塞,它不像空闲的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

    【讨论】:

      猜你喜欢
      • 2020-11-20
      • 2019-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      相关资源
      最近更新 更多