Qt QThread的moveToThread方法使用

Qt线程简介

从 Qt4.4 版本之后,因为 QThread 的 run 方法创建新线程这样实现与 Qt 设计的理念不符,Qt 主推使用 moveToThread 方法来创建新线程。QThread 应该被看做是操作系统线程的接口或控制点,而不应该包含需要在新线程中运行的代码。需要运行的代码应该放到一个 QObject 的子类中,然后将该子类的对象 moveToThread 到新线程中。主要操作步骤如下:

  1. 创建一个类对象 obj,创建一个线程对象 thread。
  2. 创建主线程中对象 M 与类对象 obj 链接的信号槽。
  3. 通过类对象 obj 的 moveToThread 方法将类对象 obj 移动到线程对象 thread 中。
  4. 调用线程对象 thread 的 start 方法,启动线程。
  5. 对象 M 调用信号槽,类对象 obj 在新线程中处理数据(调用新线程只能通过信号槽来完成,如果要将类对象 obj 的数据传回给对象 M,可以由 obj 发起对 M 的信号槽)。

具体代码如下:

1:要放入新线程的 Worker 类

h 文件:

#ifndef WORKER_H
#define WORKER_H

#include 

/*****************************************************************************************
  @copyright 2013-2020
  @author    qiaowei
  @contact   [email protected]
  @version   1.0
  @date      2021-01-09
  @brief     工人类,主要方法do_something打印工人对象所在线程的id
******************************************************************************************/
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);

signals:
    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-24
     @brief    调用Controller::print_thread方法
    ***************************************************************************/
    void result_ready(const QString& content);

public slots:
    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-07
     @brief    打印Worker对象所在线程id
    ***************************************************************************/
    void do_something();

};

#endif // WORKER_H

cpp 文件:

#include 
#include 
#include "worker.h"

Worker::Worker(QObject *parent) : QObject(parent)
{

}

void Worker::do_something()
{
    emit result_ready("Hello");

//    int i(0);
//    while (i < 20) {
//        qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
//        ++i;
//    }
    qDebug() << "I'm working in Worker's thread:" << (quint64) QThread::currentThreadId();
}

2:操纵 Worker 类对象的 Controller 类

h 文件:

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include 

QT_BEGIN_NAMESPACE
class Worker;
QT_END_NAMESPACE

/*****************************************************************************************
  @copyright 2013-2020
  @author    qiaowei
  @contact   [email protected]
  @version   1.0
  @date      2021-01-06
  @brief     控制线程创建、启动
******************************************************************************************/
class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = nullptr);

    ~Controller();

    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-06
     @brief    将对象worker_移入子线程work_thread_,启动子线程
    ***************************************************************************/
    void move_work_to_thread();

signals:
    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-07
     @brief    调用worker_::do_something方法
    ***************************************************************************/
    void start_running();

public slots:
    void print_thread() const;

private:
    void setup_connections();

    void print_thread_id() const;

private:
    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-07
     @brief    子线程
    ***************************************************************************/
    QThread* work_thread_;

    /***************************************************************************
     @author   qiaowei
     @version  1.0
     @date     2021-01-07
     @brief    放入子线程work_thread_的对象worker_
    ***************************************************************************/
    Worker* worker_;
};

#endif // CONTROLLER_H

cpp 文件:

#include 
#include 
#include "controller.h"

#include "worker.h"

Controller::Controller(QObject *parent) :
    QObject(parent),
    work_thread_(new QThread()),
    worker_(new Worker())
{
    setup_connections();

    print_thread_id();

    move_work_to_thread();
}

Controller::~Controller()
{
    work_thread_->quit();
    work_thread_->wait();

    delete work_thread_;

    if (nullptr == work_thread_) {
        qDebug()<< "nullptr";
    } else {
        work_thread_ = nullptr;
    }
}

void Controller::move_work_to_thread()
{
    worker_->moveToThread(work_thread_);

    // 启动子线程。不启动子线程,worker_对象的方法不会被调用(因为运行的环境没启动)
    work_thread_->start();
}

void Controller::print_thread() const
{
//    int i(0);
//
//    while (i < 20) {
//        print_thread_id();
//        ++i;
//    }
    print_thread_id();
}

void Controller::setup_connections()
{
    connect(this,
            &Controller::start_running,
            worker_,
            &Worker::do_something);

    connect(worker_,
            &Worker::result_ready,
            this,
            &Controller::print_thread);
}

void Controller::print_thread_id() const
{
    qDebug()<< "Controller::Controller = " << (quint64) QThread::currentThreadId();
}

触发线程的 ui 类

h 文件:

#ifndef CONTROLLER_DIALOG_H
#define CONTROLLER_DIALOG_H

#include 

QT_BEGIN_NAMESPACE
class Controller;
QT_END_NAMESPACE

namespace Ui {
class Controller_dialog;
}

/*****************************************************************************************
  @copyright 2013-2020
  @author    qiaowei
  @contact   [email protected]
  @version   1.0
  @date      2021-01-09
  @brief     操作多线程的ui
******************************************************************************************/
class Controller_dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Controller_dialog(QWidget *parent = nullptr);
    ~Controller_dialog();

private:
    void setup_connections();

private:
    Ui::Controller_dialog *ui;

    Controller* controller_;
};

#endif // CONTROLLER_DIALOG_H

cpp 文件:

#include "controller_dialog.h"
#include "ui_controller_dialog.h"

#include "controller.h"

Controller_dialog::Controller_dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Controller_dialog),
    controller_(new Controller())
{
    ui->setupUi(this);

    setup_connections();
    setFixedSize(sizeHint());
}

Controller_dialog::~Controller_dialog()
{
    delete ui;
    delete controller_;
}

void Controller_dialog::setup_connections()
{
    // 启动新线程
    connect(ui->start_button_,
            &QPushButton::clicked,
            controller_,
            &Controller::start_running);

    // 关闭所有窗体,退出程序
    connect(ui->quit_button_,
            &QPushButton::clicked,
            qApp,
            &QApplication::closeAllWindows);
}

界面 ui:



 Controller_dialog
 
  
   
    0
    0
    219
    83
   
  
  
   Dialog
  
  
   
    
     
      
       
        Start Button
       
      
     
     
      
       
        Quit
       
      
     
    
   
  
 
 
 

main 文件:

#include 

#include "mainwindow.h"
#include "thread_dialog.h"
#include "controller_dialog.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Controller_dialog d;
    d.show();

    return a.exec();
}

运行结果,打印 Print_thread、Worker 对象的线程号:

Qt QThread的moveToThread方法使用_第1张图片

 可以看到打印结果,Worker 对象在线程 9480,主程序入口在线程 5336

你可能感兴趣的:(Qt&Pyside,C&C++,qt,开发语言,c++)