Qt QThread的moveToThread方法使用

news2024/11/17 11:50:07

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_NAMESPACE

namespace 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_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:

<?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.coloradmin.cn/o/838101.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++数据结构之BST(二叉搜索树)的实现

目录 01.BST的介绍02.BST 要实现的对外方法03.摘要04.查找节点4.1四个引用&#xff0c;都有妙用4.2递归版4.3非递归版 05.插入节点5.1利用search的返回值5.2更新高度的注意事项5.3插入算法的完整代码 06.删除节点6.1框架6.2单分支&#xff0c;直接替代6.3双分支&#xff0c;化繁…

实现天气预报走势图

实现效果&#xff1a; 这里我用的天气接口是网上开源的&#xff0c;可以自己找一下。 稍微简单封装了一下axiso以及接口 封装的axios&#xff1a; // import { useUserStore } from /stores/user import axios from axios import router from /router import { ElMessage } f…

P14 电路定理——巧妙-灵性-智慧

1、替代定理 图示表示&#xff1a; 叠加定理和齐性定理只能用于线性电路&#xff0c;但是替代定理无论线不线性都可以用。 常见的&#xff1a;线性电路将某复杂支路等效成电压源或电流源之后&#xff0c;就可以使用叠加原理了。 引入两个相互抵消的电压源&#xff0c;拿其中一…

【数字IC基础】低功耗设计

低功耗技术 功耗构成静态功耗(漏电功耗)动态功耗翻转功耗(Switch Power)短路功耗(Internal Power) 不同类型的标准单元的功耗 低功耗设计方法降低芯片工作电压多阈值工艺方法电源门控&#xff08;Power Gating&#xff09;多电压域(Multi-Voltage Domain)体偏置门控时钟一个简单…

AWS Amplify 部署node版本18报错修复

Amplify env&#xff1a;Amazon Linux:2 Build Error : Specified Node 18 but GLIBC_2.27 or GLIBC_2.28 not found on build 一、原因 报错原因是因为默认情况下&#xff0c;AWS Amplify 使用 Amazon Linux:2 作为其构建镜像&#xff0c;并自带 GLIBC 2.26。不过&#xff0c;…

【M波段2D双树(希尔伯特)小波多分量图像去噪】基于定向M波段双树(希尔伯特)小波对多分量/彩色图像进行降噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

使用 OpenCV 和 Python 卡通化图像-附源码

介绍 在本文中,我们将构建一个有趣的应用程序,它将卡通化提供给它的图像。为了构建这个卡通化器应用程序,我们将使用 python 和 OpenCV。这是机器学习令人兴奋的应用之一。在构建此应用程序时,我们还将了解如何使用 easygui、Tkinter 等库。在这里,您必须选择图像,然后应…

二叉树的遍历(先序遍历,中序遍历,后序遍历)递归与非递归算法

目录 一、先序遍历题目链接1.递归2.非递归 二、中序遍历题目链接1.递归2.非递归 三、后序遍历题目链接1.递归2.非递归 一、先序遍历 先序遍历&#xff1a;先遍历一颗树的根节点&#xff0c;后遍历左子树&#xff0c;最后遍历右子树 先序遍历序列&#xff1a; 1 -> 2 -> 4…

20.4 HTML 表单

1. form表单 <form>标签: 用于创建一个表单, 通过表单, 用户可以向网站提交数据. 表单可以包含文本输入字段, 复选框, 单选按钮, 下拉列表, 提交按钮等等. 当用户提交表单时, 表单数据会发送到服务器进行处理.action属性: 应指向一个能够处理表单数据的服务器端脚本或UR…

vue使用拖拽功能实现仓库存放货物的需求

效果&#xff1a; 代码 <template><div><div class"bigTitle">xxxxxxxxxxxxxx仓库拖拽系统</div><div class"container2 flex-j-space-between"><div class"product-list"><div class"leftTree h…

Python入门【​try和except结构、常见异常、with上下文管理 、traceback模块和生成异常日志、自定义异常类】(十八)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

【C++】STL——stack和queue的模拟实现、空间适配器、deque的介绍、增删查改函数的简单实现

文章目录 1.deque的简单介绍2.模拟实现stack3.模拟实现queue 1.deque的简单介绍 deque的介绍文档 deque(双端队列)&#xff1a;是一种双开口的"连续"空间的数据结构&#xff0c;双开口的含义是&#xff1a;可以在头尾两端进行插入和删除操作&#xff0c;且时间复杂度…

实现多线程的三种方式

1. 继承Thread 类实现多线程 想要实现多线程&#xff0c;第一种方法就是通过继承Thread类实现多线程&#xff0c;有以下几步 &#xff08;1&#xff09;我们要先自定义一个类然后继承Thread类&#xff1b; &#xff08;2&#xff09;在继承Trread的类中重写 run 方法&#x…

成功了!|| Poetry安装pytorch || 整理自github项目Poetry下的issue

在使用Poetry安装pytorch的时候&#xff0c;常常会遇到各种问题&#xff1a;首先是使用add添加时&#xff0c;会说只有torch没有什么pytorch&#xff0c;很显然&#xff0c;它是直接针对包的&#xff0c;第二点是&#xff0c;如果是一台没有nvidia显卡的机器&#xff0c;由于po…

CISA《网络安全事件和漏洞响应手册》提到的SSVC是什么?

2021年11月16日&#xff0c;美国网络安全和基础设施安全局(CISA)根据行政命令EO 14028的要求发布了《网络安全事件和漏洞响应手册》。手册规定的漏洞响应过程包括识别、评估、修复、报告通知4个步骤&#xff0c;其中评估部分的第一句话提到“使用特定相关者漏洞分类法(Stakehol…

C++ 动态内存分配

在C中动态内存的分配技术可以保证程序在允许过程中按照实际需要申请适量的内存&#xff0c;使用结束后还可以释放&#xff0c;这种在程序运行过程中申请和释放的存储单元也称为堆。 申请和释放过程一般称为建立和删除。 在C程序中&#xff0c;建立和删除堆对象使用两个运算符&…

html页面input设置日期和时分秒组件方法

html <input class"form-control" type"datetime-local" step"01">效果图

Java根据坐标经纬度计算两点距离(5种方法)、校验经纬度是否在圆/多边形区域内的算法推荐

目录 前言 一、根据坐标经纬度计算两点距离&#xff08;5种方法&#xff09; 1.方法一 2.方法二 3.方法三 4.方法四 5.方法五 5.1 POM引入第三方依赖 5.2 代码 6.测试结果对比 二、校验经纬度是否在制定区域内 1.判断一个坐标是否在圆形区域内 2.判断一个坐标是否…

安防监控国标GB28181平台EasyGBS视频快照无法显示是什么原因?如何解决?

安防视频监控国标视频云服务EasyGBS支持设备/平台通过国标GB28181协议注册接入&#xff0c;并能实现视频的实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。平台部署简单、可拓展性强&#xff0c;支持将接入的视频流进行全终端、全平台分发&#xff…