qt多线程使用方式

2023-11-18

有5个方式:可以参考这个博客:Qt 中开启线程的五种方式_qt 线程_lucky-billy的博客-CSDN博客

注:为了实现更加灵活的线程管理(因为这5种都有一些不方便之处:QThread需要子类化且不能传参,moveToThread不能传参且只能移入一个对象而不是一个函数,QThreadPool 需要子类化QRunnable且只能启动一个对象,QtConcurrent支持传参但是不能管理它,std::thread能够传入函数以及给定实参但是不是qt方式了),我自己实现了一个更好用的线程管理类(支持指定一个函数,同时指定传入的实参,而且能管理该线程例如随时终止等),看我这个博客: qt自己实现方便的线程管理类_我是标同学的博客-CSDN博客

接下来,讲解这5种方式情况: 

1. 继承 QThread 重写 run 函数

class Thread : public QThread
{
    Q_OBJECT
public:
    virtual void run() override;
}
优点:构造使用方式简单,所有操作都放在run()方法里面。而且可以随时停止,因为这是以线程对象形式存在,我们可以对其进行各种管理。
缺点:不够灵活,只能运行run()里面的程序。此外,传入的函数不能同时给参数,只能另外一个函数设置其成员变量,run函数里读取该成员变量。

2. 继承 QObject 调用 moveToThread

QThread th;
Test test;
test.moveToThread(&th);
优点:使用简单,可以使用信号槽通信,很灵活。
缺点:每次都要创建线程,带来不必要资源开支。而且是整个对象给弄进去,也挺重的。

3. 继承 QRunnable 重新 run 函数,结合 QThreadPool 实现线程池

我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

还有一个问题需要注意一下,QThread 是集成自 QObject 的,我们通常会使用信号槽与外界进行通信。而 QRunnable 并不是继承自 QObject 类的,所以他无法使用信号槽机制进行通信。这里推荐两种方法,一个是使用 QMetaObject::invokeMethod()函数。另一个是使用多重继承的方法,自定义类需要同时继承自 QRunnable 和 QObject

每个Qt应用程序都有一个全局 QThreadPool 对象,可以通过调用 globalInstance() 来访问它。==也可以单独创建一个 QThreadPool 对象使用。

class BPrint : public QRunnable
{
    void run()
    {
        for ( int count = 0; count < 5; ++count )
        {
            qDebug() << QThread::currentThread();
            QThread::msleep(1000);
        }
    }
};

一般情况下,我们不需要在 Qt 程序中创建线程池对象,**直接使用 Qt 为每个应用程序提供的线程池全局对象即可。得到线程池对象之后,调用 start() 方法**就可以将一个任务添加到线程池中,这个任务就可以被线程池内部的线程池处理掉了,使用线程池比自己创建线程的这种多种多线程方式更加简单和易于维护。
 

4. 使用 C++ 11 中的 std::thread

#include <thread>
void threadfun1()
{
    std::cout << "threadfun1 - 1\r\n" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "threadfun1 - 2" << std::endl;
}

void threadfun2(int iParam, std::string sParam)
{
    std::cout << "threadfun2 - 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "threadfun2 - 2" << std::endl;
}

int main()
{
    std::thread t1(threadfun1);
    std::thread t2(threadfun2, 10, "abc");
    t1.join();        // 等待线程 t1 执行完毕
    std::cout << "join" << std::endl;
    t2.detach();    // 将线程 t2 与主线程分离
    std::cout << "detach" << std::endl;
}
t1.join() 会等待t1线程退出后才继续往下执行t2.detach() 并不会等待,detach字符输出后,主函数退出,threadfun2还未执行完成,但是在主线程退出后,t2的线程也被已经被强退出

5. Qt QtConcurrent 之 Run 函数

简单来说,QtConcurrent::run() 函数会在一个单独的线程中执行,并且该线程取自全局 QThreadPool,该函数的返回值通过 QFuture API 提供。

// 需要传递的参数,则跟在函数名之后,依次加入 QFuture<void> future = QtConcurrent::run(FuncWithArguments, integer, string);

...

QString result = future.result();

需要注意的是:
1)该函数可能不会立即运行; 函数只有在线程可用时才会运行
2)通过 QtConcurrent::run() 返回的 QFuture 不支持取消、暂停,返回的 QFuture 只能用于查询函数的运行/完成状态和返回值
3) Qt Concurrent 已经从 QtCore 中移除并成为了一个独立的模块,所以想要使用 QtConcurrent 需要在 pro 文件中导入模块:
QT += concurrent
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

qt多线程使用方式 的相关文章

  • 如何让小部件在上下文菜单出现时接收鼠标释放事件

    在Ubuntu20 04上 当上下文菜单出现时 我无法让小部件接收鼠标释放事件 而Windows可以接收 我的pyqt版本是5 15 2 我考虑过手动发送鼠标释放事件 但我不知道当上下文菜单出现时哪些系统会收到鼠标释放事件 这样做可能会导致
  • Retina 显示屏中具有 QOpenGLWIdget 的 Qt MainWindow 显示错误大小

    我有一个 Qt 应用程序MainWindow 我嵌入一个QOpenGLWidget在里面 一切正常 直到我开始使用 Apple Retina 显示屏并在高 DPI 模式下运行我的应用程序 我的QOpenGLWidget只是它应该具有的大小的
  • 使用 OpenGL 渲染 QImage

    与我相关的其他问题 https stackoverflow com questions 20126354 render qimage from sooffscreenrenderer in qglwidget 我认为更核心的问题是 如何渲染
  • 如何去除QWizard中的水平线?

    我正在研究一个样式表QWizard我想删除按钮上方的水平线 我尝试递归浏览所有小部件并将其边框设置为无 但似乎没有任何小部件具有此边框 这是我的代码 可以找到完整的可构建示例here https gist github com ardeid
  • 是否有 Qt 小部件可以浏览应用程序中小部件的层次结构(类似于 Spy++)?

    我们有一个具有复杂的小部件层次结构的应用程序 我希望能够以与 Spy 类似的方式浏览此层次结构 查看和编辑属性 例如大小 如果有一个小部件可以显示此信息 则它不需要在外部应用程序中运行 那么问题来了 这样的神兽存在吗 您可以使用Gammar
  • 无法运行 Qt 应用程序:找不到版本“Qt_5”

    我运行 Ubuntu 16 04 LTS 我的问题是我无法运行可以编译的 Qt5 应用程序 这是我尝试运行它时得到的结果 home user Desktop sconfig dist Release GNU Linux SCongif us
  • QTabWidget 选项卡在垂直方向,但文本在水平方向

    我正在尝试用 C Qt 制作一个带有这样的侧边栏的应用程序 但是当将 QTabWidget 方向设置为西时 它会使文本垂直 如何让文本位于左侧 但水平对齐 PS 我不需要图标 提前致谢 您可以使用QListWidget http doc q
  • QML 列表视图拖放

    我想创建两个 qml 列表视图 可以执行两个功能 拖放一个列表中的项目以更改项目的顺序 跨列表拖放项目 项目将从一个列表中删除并添加到另一个列表中 根据 Qt 文档中的拖放示例 我决定创建两个访问同一列表模型的列表视图 列表模型中的每个项目
  • Qt 支持 Windows 蓝牙 API 吗?

    谁能告诉我 Qt 是否支持 Windows 蓝牙 API 如果是这样 您能否分享一些有关如何使用它的信息 自上次答复以来 这个问题的答案发生了一些变化 Qt 5 2 版为 Linux BlueZ 和 BlackBerry 设备实现了蓝牙 A
  • 为什么 QT 设计器重新调整大小或不允许我缩小或展开小部件或按钮?

    很多时候 在使用 QT 设计器时 我发现自己需要通过缩小或扩展来调整事物的大小 每当我尝试这样做时 程序都不允许我这样做 而只是恢复到将对象放置在窗口中时给我的原始默认大小 无论我的布局如何 为什么要这样做 是否有可能改变这一点 以便我可以
  • QAbstractItemModel 如何表示树?

    我仍然很难理解 QAbstractItemModel 对项目的表示 有两种返回 QModelIndex 项的方法对我来说没有任何意义 QModelIndex QAbstractItemModel index int row int colu
  • 在 Qt 中,许多插槽连接到同一信号,它们在发出信号时是否按顺序调用?

    In the Qt文件说 如果多个插槽连接到一个信号 则这些插槽将 按照它们连接的顺序一个接一个地执行 当信号发出时 但在connect 功能 设置Qt ConnectionType输入为Qt QueuedConnection意思是 当控制
  • 如何将 QFile 与 std::iostream 一起使用?

    是否可以像 std iostream 一样使用 QFile 我很确定那里一定有一个包装纸 问题是在哪里 我有另一个库 它需要 std istream 作为输入参数 但在我的程序中 此时我只有一个 QFile 我使用以下代码提出了自己的解决方
  • QObject 通用信号处理程序

    信号处理程序 是指插槽 而不是 POSIX 信号的处理程序 我需要 连接 可能不会 using QObject connect直接地 所有信号从 QObject 的 未知 子类的实例到一个单槽另一个 QObject 的 我需要这个才能通过网
  • 是否可以根据 QSlider 的位置来改变其手柄的颜色?

    我非常清楚如何通过样式表自定义 QSlider 但我想知道是否可以执行以下操作 我希望滑块的手柄从蓝色变为黄色 当设置在左侧时 它是蓝色的 设置在左侧时 它是蓝色的 当你将它向右移动时 它会出现从蓝色到黄色的渐变 如果可以通过样式表 如何实
  • 使用 QNetworkAccessManager 的 Qt 控制台应用程序

    我正在尝试写一个Qt调用网络服务的应用程序 这是一个控制台应用程序 url 将作为命令行参数传入 我搜索了例如http程序在Qt并找到这个链接 http qt project org doc qt 5 qnetworkaccessmanag
  • Qt - 如何使用 QNetworkAccessmanager 获取响应文本

    这是我的代码 Widget Widget manager new QNetworkAccessManager this connect manager SIGNAL finished QNetworkReply this SLOT repl
  • 如何为 Windows 安装开源 Qt 库 5 二进制版本

    这个问题具体是关于Qt libraries 5 0 0 for Windows VS 2010 406 MB at http qt project org downloads http qt project org downloads 但我
  • 使用 QWT 构建时出错

    我收到一个错误 undefined reference to QwtPlot QwtPlot QWidget 当我尝试构建我的项目时 即使设置中一切看起来都很好 在我的 CmakeLists txt 中我有 include director
  • 一个具有完全透明背景的qt小部件

    我需要创建一个 qt 小部件 它将充当其他一些小部件的父级 并对它们进行排序 现在的问题是如何使其背景完全透明 我想这样做 struct Imp Imp QWidget parent thisWidget new QWidget paren

随机推荐

  • java -jar后台启动的四种方式

    Linux系统启动java项目四种方法 1 用java jar xxx jar 点击回车就会启动成功 但是当退出或者关闭远程工具就会把进程关闭 以上就是启动的项目Java jar xxx jar 但是点击过Ctl c或者把此窗口关闭 就会杀
  • 【Linux】shell命令与文件权限

    目录 前言 shell命令以及运行原理 Linux权限的概念 1 文件访问者的分类 人 2 文件类型和访问权限 事物属性 3 文件权限值的表示方法 4 文件访问权限的相关设置方法 4 1 chmod指令 4 2 chown指令 4 3 ch
  • 计算机应届博士生的一点求职经验——华为篇

    一点也许有用的求职经验与感悟 前言 机考 技术面试 主管面试 HR面试 性格测试 思考与选择 前言 华为的应届生申请可以填写2个志愿 一共有五道考核 机考 必做 2轮技术面试 部门主管面试 HR 面试和性格测试 本文会对这几个方面分别展开
  • 解决neo4j导入数据时报错:neo4j already contains data, cannot do import here报错

    完整报错如下 java lang IllegalStateException neo4j already contains data cannot do import here at org neo4j internal batchimpo
  • Android Webview 部分图片显示不出来问题

    最近发现在华为Mate 10 上面我们app的内置webview会有部分图片不展示 直接就图裂了 经过绕了一大圈后才解决了问题 其实问题原因很简单 但是分析过程不顺利 拿出来分享下 希望可以帮助大家少走弯路 简单说下这个问题的背景 1 我们
  • Geoffrey Hinton、姚期智、张钹、Sam Altman等专家共话AI安全与对齐丨2023智源大会议程公开...

    6月9日 2023北京智源大会 将邀请AI领域的探索者 实践者 以及关心智能科学的每个人 共同拉开未来舞台的帷幕 你准备好了吗 与会知名嘉宾包括 图灵奖得主Yann LeCun OpenAI创始人Sam Altman 图灵奖得主Geoffr
  • stata如何看某个命令的options?即逗号后面可以加上哪些命令

    以codebook这一命令为例 在命令窗口输入 help codebook 则会出现以下内容
  • mysql text多少字节_mysql里面text能存多大的数据

    展开全部 最多可以存储65535字节来数据 源 在mysql中 文本文件bai存储从0到65 535字节 du64KB 的字节 因此 mysql中的文zhi本最多可以dao存储65 535字节 文本文件有四种类型 tinytext Text
  • 05_numpy学习笔记(下):大作业

    大作业回顾 1 导入鸢尾属植物数据集 保持文本不变 知识点 输入和输出 如何导入存在数字和文本的数据集 numpy loadtxt 2 求出鸢尾属植物萼片长度的平均值 中位数和标准差 第1列 sepallength 知识点 统计相关 如何计
  • vue3组件之间通信(三)——爷孙组件传递属性和方法

    文章目录 1 setup函数传递属性和方法 attrs 1 代码 2 主要代码和详细讲解 3 注意点 2 script setup 语法糖传递属性和方法 1 代码 2 主要代码和详细讲解 3 注意点 前言 爷孙组件使用prop一层一层传值和
  • drag diffusion中的gradio代码逐行解析

    gradio库是一个用于创建简单web应用程序的库 允许用户通过浏览器和程序进行交互 1 gr Blocks 使用with创建 在with中创建的任何组件都会自动添加到应用程序中 组件按创建顺序垂直显示在应用中 Blocks 模块用于组件在
  • Swoole从入门到入土(18)——WebSocket服务器[心跳ping]

    由于 WebSocket 是长连接 如果一定时间内没有通讯 连接可能会断开 这时候需要心跳机制 WebSocket 协议包含了 Ping 和 Pong 两个帧 可以定时发送 Ping 帧来保持长连接 1 心跳原理图 2 websocket协
  • 【语言环境】WAMP环境部署及优化—以win2008R2SP1为操作系统

    这里写目录标题 1 WAMP环境简介 2 WAMP环境部署详细过程 2 1 要求 2 2 虚拟机安装win2008R2SP1 2 2 1 安装前准备 2 2 2 在VMware里创新新的虚拟机 2 2 3 在虚拟机里装win2008R2SP
  • 软件外包开发的流程图工具

    软件开发过程中需要画流程图 可以更清楚的表达软件业务流程 减少在开发过程中的业务理解偏差 因此在软件开发过程中流程图工具是必不可少的软件管理工具 今天和大家分享常见的一些软件流程图工具 每款工具都有其自身的特色 用户可以根据自身的需求选择合
  • OnEnable方法详解(Unity)

    OnEnable方法详解 介绍 在Unity中 OnEnable是一个生命周期方法 用于在脚本或组件被激活时执行特定的操作 当启用对象或启用脚本时 Unity会自动调用OnEnable方法 这使得我们可以在脚本激活时执行一些初始化任务或准备
  • mysql PXC集群脑裂及grastate.dat修改实验

    三台服务器做了 mysql PXC 集群 172 31 217 182 bd dev mingshuo 182 172 31 217 183 bd dev mingshuo 183 172 31 217 89 bd dev vertica
  • android 侦听apk安装成功,再执行界面的更新操作

    这是我项目里需要在安装完应用后 马上能侦听到新的应用安装成功 并且更新相应的界面用到的 1 项目里添加侦听类 然后配置文件加权限 就ok import android content BroadcastReceiver import and
  • 如何快速搭建全链路平台,展示服务拓扑以分析性能

    写在前面的话 限于本文作者水平 仅仅以node为web server和后端 数据库采用mongodb 来展示全链路的可视化 全链路可视化的必要性 微服务架构越来越流行 技术中台部 基础架构部等部门的分工也越来越精细化 原本一次请求可能只涉及
  • 计算机网络——应用层之电子邮件(E-mail)

    一 基本概念 电子邮件 E mail 是目前Internet上使用最频繁的服务之一 电子邮件是以电子方式发送传递的邮件 只要通信双方都有电子邮件地址 便可以电子传播为媒介 交互邮件 Internet上电子邮件系统采用客户机 服务器模式 信件
  • qt多线程使用方式

    有5个方式 可以参考这个博客 Qt 中开启线程的五种方式 qt 线程 lucky billy的博客 CSDN博客 注 为了实现更加灵活的线程管理 因为这5种都有一些不方便之处 QThread需要子类化且不能传参 moveToThread不能