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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kodi 电视遥控器 不起作用 ,无法唤醒视频OSD

最近电视盒子上安装了kodi播放器&#xff0c;但是安装好之后&#xff0c;盒子本身的遥控器就不起作用了&#xff0c;之前看网络上其他的文章&#xff0c;需要重新安装tv 控制器&#xff0c;重新映射&#xff0c;比较麻烦&#xff0c;而且观看视频的时候没办法唤起OSD切换字幕和…

在美国,信用分数超过800,这是一个很好的分数吗?

超过800的信用评分被认为是极好的&#xff0c;而且这确实是可以实现的。事实上&#xff0c;美国有很多人的信用评分都在这个范围内。 信用评分是一个数字化的表示&#xff0c;反映了一个人的信用值得信赖度&#xff0c;贷款机构用它来评估这个人偿还债务的可能性。最广泛使用的…

PyCharm安装使用2023年教程,PyCharm与现流行所有编辑器对比。

与PyCharm类似的功能和特性的集成开发环境&#xff08;IDE&#xff09;和代码编辑器有以下几种&#xff1a; Visual Studio Code&#xff08;VS Code&#xff09;&#xff1a;由Microsoft开发&#xff0c;VS Code是一个高度可定制和可扩展的代码编辑器。它支持多种编程语言&am…

为什么list.sort()比Stream().sorted()更快?

真的更好吗&#xff1f; 先简单写个demo List<Integer> userList new ArrayList<>();Random rand new Random();for (int i 0; i < 10000 ; i) {userList.add(rand.nextInt(1000));}List<Integer> userList2 new ArrayList<>();userList2.add…

ORA-48913: Writing into trace file failed, file size limit [50000000] reached

检查某环境的alert_orcl1.log时&#xff0c;发现有很多的ORA-48913报错&#xff0c;细节如下 Sat Jul 22 19:34:04 2023 Non critical error ORA-48913 caught while writing to trace file "/u01/app/oracle/diag/rdbms/orcl/orcl1/trace/orcl1_dw00_138010.trc" E…

LeetCode 热题 100 JavaScript--108. 将有序数组转换为二叉搜索树

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 提示&#xff1a; 1 < nums.length < 104 -104 < n…

C#利用自定义特性以及反射,来提大型项目的开发的效率

在大型项目的开发过程中&#xff0c;需要多人协同工作&#xff0c;来加速项目完成进度。 比如一个软件有100个form&#xff0c;分给100个人来写&#xff0c;每个人完成自己的Form.cs的编写之后&#xff0c;要在Mainform调用自己写的Form。 如果按照正常的Form form1 new For…

摄像头电池组和平衡车电池组

摄像头电池组 Wh~是电量 Wh V*Ah 毫安(mA)~是电流 电量是9.62Wh&#xff0c;电压是 3.7v 9.62 wh / 3.7v 2.6 Ah 2600mAH 4个并联电池&#xff1a;10400mAH / 4 2600mAH PH2.0mm-2Pins 平衡车 72 wh / 36v 2 Ah 2000mAH 对比自己买的单粒电池 vs 摄像头和平衡车的 …

云安全攻防(四)之 云原生技术

云原生技术 容器技术 容器与虚拟化 虚拟化&#xff08;Virtualization&#xff09;和容器&#xff08;Container&#xff09;都是系统虚拟化的实现技术&#xff0c;可实现系统资源的”一虚多“共享。容器技术可以理解成一种”轻量的虚拟化“方式&#xff0c;此处的”轻量“主…

JNI之Java实现远程打印

打印机是最常见的办公设备了。一般情况下如果需要实现打印&#xff0c;可通过前端print.js包来完成。但是&#xff0c;如果要实现智能办公打印&#xff0c;就可以使用JNI技术、封装接口、远程调用实现完成。 导包 jacob&#xff1a;Java COM Bridge <dependency><g…

vim粘贴内容格式混乱解决方法

问题 复制本地文件内容后&#xff0c;咱贴到vim文本内&#xff0c;格式错乱 解决方法 打开vim配置文件 最后面加入一行 vim /etc/vimrc set pastetoggle<F11> 开发vim文件&#xff0c;进入后先按F11进入交互模式 shift insert 再次粘贴 解决

原型模式(C++)

定义 使用原型实例指定创建对象的种类&#xff0c;然后通过拷贝这些原型来创建新的对象。 应用场景 在软件系统中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作;由于需求的变化&#xff0c;这些对象经常面临着剧烈的变化&#xff0c;但是它们却拥有比较稳定一致的…

SpringCloud Gateway获取请求响应body大小

前提 本文获取请求、响应body大小方法的前提 : 网关只做转发逻辑&#xff0c;不修改请求、相应的body内容。 SpringCloud Gateway内部的机制类似下图&#xff0c;HttpServer&#xff08;也就是NettyServer&#xff09;接收外部的请求&#xff0c;在Gateway内部请求将会通过Htt…

外部排序算法总结

一.内排总结 在之前博客里&#xff0c;博主已经介绍了各种内部排序算法的原理和C语言代码实现&#xff0c;不懂的朋友可以在同系列专栏里选择查看&#xff0c;今天介绍常见排序算法的最后一点&#xff0c;也就是外部排序。在此之前&#xff0c;我们先对外部排序的各种算法做一…

高翔《自动驾驶中的SLAM技术》代码详解 — 第6章 2D SLAM

目录 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 // src/ch6/test_2dlidar_io.cc // Created by xiang on 2022/3/15. // #include <gflags/gflags.h> #include <glog/logging.h> #include <opencv2/highgui.hpp>…

Redis—全局命令

Redis—全局命令 &#x1f50e;get / set&#x1f50e;常用全局命令keysexistsdelexpirettlkey 的过期策略type Redis 官网 Redis 中的命令不区分大小写 进入 Redis 客户端 redis-cli -h Redis 服务器的 IP 地址 -p Redis 服务器的端口号省略 -h 表示 Redis 服务器的 IP 地址…

OKR管理策略:为开发团队注入动力

引言 在这个快速变化的世界中&#xff0c;公司需要迅速应对市场变化&#xff0c;并保持其目标和战略的清晰性和一致性。而OKR&#xff08;Objectives and Key Results&#xff09;正是这个挑战的解决方案之一。OKR的实施可以帮助开发团队明确目标&#xff0c;关注关键结果&…

powershell几句话设置环境变量

设置环境变量比较繁琐&#xff0c;现在用这段话&#xff0c;在powershell中就可以轻松完成。 $existingPath [Environment]::GetEnvironmentVariable("Path", "Machine") $newPath "C:\Your\Path\Here"if ($existingPath -split ";"…

DSP学习笔记

一个汇编语句包含4个固定顺序的区域&#xff1a;标号&#xff08;必须从第一列开始 不能空格&#xff0c;后面可以有&#xff1a;也可以没有&#xff09; 助记符 操作数 注释&#xff08;用分号或者星号来注释&#xff09;伪指令用.开头&#xff0c;注释可以用第一列开始写&…

软件设计师(五)软件工程基础知识

一、软件工程概述 软件开发和维护过程中所遇到的各种问题称为“软件危机”。 软件工程是指应用计算机科学、数学及管理科学等原理&#xff0c;以工程化的原则和方法来解决软件问题的工程&#xff0c;其目的是提高软件生产率、提高软件质量、降低软件成本。 #mermaid-svg-h3j6K…