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 <QObject>/*****************************************************************************************@copyright 2013-2020@author    qiaowei@contact   weiweiqiao@126.com@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 <QtDebug>
#include <QThread>
#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 <QObject>QT_BEGIN_NAMESPACE
class Worker;
QT_END_NAMESPACE/*****************************************************************************************@copyright 2013-2020@author    qiaowei@contact   weiweiqiao@126.com@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 <QThread>
#include <QtDebug>
#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 <QDialog>QT_BEGIN_NAMESPACE
class Controller;
QT_END_NAMESPACEnamespace Ui {
class Controller_dialog;
}/*****************************************************************************************@copyright 2013-2020@author    qiaowei@contact   weiweiqiao@126.com@version   1.0@date      2021-01-09@brief     操作多线程的ui
******************************************************************************************/
class Controller_dialog : public QDialog
{Q_OBJECTpublic: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:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>Controller_dialog</class><widget class="QDialog" name="Controller_dialog"><property name="geometry"><rect><x>0</x><y>0</y><width>219</width><height>83</height></rect></property><property name="windowTitle"><string>Dialog</string></property><layout class="QGridLayout" name="gridLayout"><item row="0" column="0"><layout class="QHBoxLayout" name="horizontalLayout"><item><widget class="QPushButton" name="start_button_"><property name="text"><string>Start Button</string></property></widget></item><item><widget class="QPushButton" name="quit_button_"><property name="text"><string>Quit</string></property></widget></item></layout></item></layout></widget><resources/><connections/>
</ui>

main 文件:

#include <QApplication>#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 对象的线程号:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/52624.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构10 -查找_树表查找

创建二叉搜索树 二叉搜索树 二叉搜索树是有数值的了&#xff0c;二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b; 若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b; 它…

在线LaTeX公式编辑器编辑公式

在线LaTeX公式编辑器编辑公式 在编辑LaTex文档时候&#xff0c;需要输入公式&#xff0c;可以使用在线LaTeX公式编辑器编辑公式&#xff0c;其链接为: 在线LaTeX公式编辑器&#xff0c;https://www.latexlive.com/home 图1 在线LaTeX公式编辑器界面 图2 在线LaTeX公式编辑器…

Spark、RDD、Hive 、Hadoop-Hive 和传统关系型数据库区别

Hive Hadoop Hive 和传统关系型数据库区别 Spark 概念 基于内存的分布式计算框架 只负责算 不负责存 spark 在离线计算 功能上 类似于mapreduce的作用 MapReduce的缺点 运行速度慢 &#xff08;没有充分利用内存&#xff09;接口比较简单&#xff0c;仅支持Map Reduce功能…

W5100S-EVB-PICO做DNS Client进行域名解析(四)

前言 在上一章节中我们用W5100S-EVB-PICO通过dhcp获取ip地址&#xff08;网关&#xff0c;子网掩码&#xff0c;dns服务器&#xff09;等信息&#xff0c;给我们的开发板配置网络信息&#xff0c;成功的接入网络中&#xff0c;那么本章将教大家如何让我们的开发板进行DNS域名解…

kubernetes基于helm部署gitlab

kubernetes基于helm部署gitlab 这篇博文介绍如何在 Kubernetes 中使用helm部署 GitLab。 先决条件 已运行的 Kubernetes 集群负载均衡器&#xff0c;为ingress-nginx控制器提供EXTERNAL-IP&#xff0c;本示例使用metallb默认存储类&#xff0c;为gitlab pods提供持久化存储&…

深度学习Redis(2):持久化

前言 在上一篇文章中&#xff0c;介绍Redis的内存模型&#xff0c;从这篇文章开始&#xff0c;将依次介绍Redis高可用相关的知识——持久化、复制(及读写分离)、哨兵、以及集群。 本文将先说明上述几种技术分别解决了Redis高可用的什么问题&#xff1b;然后详细介绍Redis的持…

HTML 基础标签

前言 当今互联网时代&#xff0c;网页是我们获取信息、交流和展示自己的重要渠道之一。而HTML&#xff08;超文本标记语言&#xff09;作为构建网页的基础&#xff0c;学习掌握HTML标签成为了必不可少的技能。 标题标签 <h1>~<h6>&#xff1a;这是用来定义标题的…

Whole Tomato Visual Assist X Crack

Whole Tomato Visual Assist X Crack Visual Assist X通过Visual Studio中的关键新功能和对现有功能的改进&#xff0c;大大缩短了应用程序开发时间&#xff0c;使您能够&#xff1a;Visual Assist提高了自动化程度&#xff0c;简化了导航&#xff0c;并在开发过程中显示重要信…

基于双端口RAM的乒乓操作测试

文章目录 前言一、乒乓操作简介二、双端口RAM配置三、RAM控制模块设计四、乒乓操作验证 前言 本文将介绍基于双端口RAM的乒乓操作测试&#xff0c;并探索如何在AWC_C4MB开发板上实现这一测试。双端口RAM作为一种性能出色且功能强大的存储器设计&#xff0c;为我们提供了并发访问…

如何与 Boot Barn 建立 EDI 连接?

Boot Barn 专注于提供各种高品质的靴子、鞋类和西部服饰。其经营范围广泛&#xff0c;为广大顾客提供最新潮流和经典款式的选择。 Boot Barn 的使命是成为顾客在西部风格时尚领域的首选购物地点。多年来&#xff0c;Boot Barn 凭借卓越的服务和优质的产品赢得了众多客户的信赖和…

OpenSource - 一站式API服务

文章目录 概述功能模块运行启动Docker启动功能预览首页接口开发接口属性请求参数在线预览应用创建接口列表数据库类型限流熔断接口申请申请审批 概述 Crabc是低代码开发平台&#xff0c;企业级API发布管理系统&#xff0c;采用SpringBoot、JWT、Mybatis等框架和SPI插件机制实现…

网络安全进阶学习第十一课——MySQL手工注入(2)

文章目录 一、UA注入1、原理2、靶场演示&#xff1a;1&#xff09;一旦页面出现如下现状&#xff0c;就可以使用UA注入2&#xff09;BP抓包3&#xff09;修改User-Agent 二、referer注入1、原理2、靶场演示&#xff1a;1&#xff09;使用BP抓包2&#xff09;修改Referer 三、DN…