QT——connect的第五个参数 Qt::ConnectionType (及qt和c++的多线程的区别)

一直对QT的多线程和c++的多线程的区别有疑惑,直到看到文档中这一部分内容才豁然开朗

一.ConnectionType参数的类型和区别


首先是官方文档中对于该枚举值的区别介绍:

对于队列(queued )连接,参数必须是 Qt 元对象系统已知的类型,因为 Qt 需要复制参数以将它们存储在后台的事件(event)中。如果您尝试使用排队连接并收到错误消息

QObject::connect: Cannot queue arguments of type 'MyType'

在建立连接之前调用 qRegisterMetaType() 来注册数据类型。

  1. Qt::AutoConnection:默认的连接类型。Qt自动决定使用直接连接(DirectConnection)还是队列连接(QueuedConnection),基于发信号的对象和接收槽的对象是否在同一个线程。

  2. Qt::DirectConnection:信号直接调用槽函数,无论槽函数所在的对象是否位于同一线程。这意味着,如果槽函数位于不同线程,必须确保槽函数是线程安全的。

  3. Qt::QueuedConnection:当信号发出时,它会被放入事件队列中。当控制权返回到接收对象所在线程的事件循环时,槽函数才会被调用。这适用于跨线程通信,确保槽函数在其所属线程的上下文中被调用。

  4. Qt::BlockingQueuedConnection:类似于QueuedConnection,但是发送信号的线程将等待接收槽函数执行完成。这种类型需谨慎使用,因为如果在同一线程内使用,它会导致死锁。

  5. Qt::UniqueConnection:确保同一信号和槽之间不会建立多个连接。

在多线程应用程序中,选择适当的ConnectionType至关重要,因为它直接影响应用程序的响应性和线程安全性。例如,若要从一个线程向另一个线程发送信号,最好使用QueuedConnection。这样可以确保信号在接收线程的上下文中被处理,从而避免线程间的竞争条件。

总之,通过合理选择ConnectionType,可以在Qt应用程序中有效地管理线程间的通信,从而提高程序的稳定性和性能。

二.该参数对多线程的影响

再思考qt中封装的多线程,可以发现,c++的库中的多线程是可以基于函数的,也就是一个没有封装到类中的普通函数可以移动到一个新开的线程中进行操作;而qt的多线程,可以参考下面官网的说法
在这里插入图片描述
其中提到:Qthread是qt中所有线程控制的基础,每个QThread实例代表且控制了一个线程,QThread可以被直接实例化或子类化。
QT的多线程,有实例化和子类化两种方式,而这两种方式都是基于类的,实例化是将需要多线程的工作函数(成员函数)的类通过moveToThread()移动到一个QThread实例中;子类化是工作函数(成员函数)的类直接继承了Qthread。Qobject对象是有线程归属的,或者说其存活在特定线程中。当接收到队列的信号或事件,槽函数或事件处理在其归属线程中执行。
这时两种方法和c++的线程库的区别就出来了,c++的线程库可以直接将一个函数丢线程中运行,不需要类的依附,比qt的简单,但qt的多线程是可以使用信号槽机制的,这就使得一个子线程的操作可以通过主线程来触发。
connect里面的第五个参数ConnectionType便起到了调整多线程中的信号槽工作方式的作用。

三.Qt多线程中信号槽机制的最佳实践及具体例子

在Qt的多线程应用中,合理使用信号槽机制可以大幅提高程序的效率和稳定性。以下是一些最佳实践和具体的例子,用于演示如何在不同场景中选择和应用正确的ConnectionType

最佳实践

  1. 数据共享与线程安全:在跨线程操作数据时,需要确保线程安全。使用信号和槽传递数据,而非直接访问共享资源,可以有效避免竞争条件。

  2. 避免阻塞:在使用BlockingQueuedConnection时要小心,避免在同一线程内使用,因为这可能导致死锁。

  3. 利用事件循环:对于跨线程的通信,使用QueuedConnection,让槽函数在其所属线程的事件循环中被调用,这样可以保证槽函数执行时线程的状态是安全的。

具体例子

例子1:跨线程更新UI

在Qt中,UI更新通常需要在主线程(GUI线程)中进行。如果在一个工作线程中需要更新UI,可以通过信号和槽来实现跨线程通信。

工作线程类

class Worker : public QObject {Q_OBJECTpublic:Worker();signals:void updateUI(const QString &text);public slots:void doWork() {// 执行一些操作QString result = "完成工作";emit updateUI(result);}
};

主线程中的槽函数

class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow();public slots:void onUpdateUI(const QString &text) {// 更新UIlabel->setText(text);}
};

连接信号和槽

Worker *worker = new Worker();
QThread *thread = new QThread();
worker->moveToThread(thread);MainWindow *window = new MainWindow();// 使用自动连接,Qt将根据情况选择Direct或Queued连接
connect(worker, &Worker::updateUI, window, &MainWindow::onUpdateUI);thread->start();

在这个例子中,当工作线程完成其任务时,它会发出一个信号,该信号携带必要的数据更新UI。由于updateUI信号连接到了主线程的槽,Qt自动使用了QueuedConnection,确保UI的更新在主线程中安全地执行。

例子2:数据处理和反馈

在一个复杂的应用中,主线程可能需要启动一个工作线程来处理数据,并在处理完成后接收反馈。

工作线程类

class DataProcessor : public QObject {Q_OBJECTpublic:DataProcessor();signals:void processingComplete(const QString &result);public slots:void processData() {// 处理数据QString result = "数据处理完成";emit processingComplete(result);}
};

主线程中的槽函数

class Controller : public QObject {Q_OBJECTpublic:Controller();public slots:void onProcessingComplete(const QString &result) {// 处理完成后的操作qDebug() << "处理结果:" << result;}
};

连接信号和槽

DataProcessor *processor = new DataProcessor();
QThread *thread = new QThread();
processor->moveToThread(thread);Controller *controller = new Controller();// 使用队列连接以确保线程安全
connect(processor, &DataProcessor::processingComplete, controller, &Controller::onProcessingComplete, Qt::QueuedConnection);thread->start();

在这个例子中,当数据处理完成时,DataProcessor类会发出processingComplete信号。由于这个信号连接到了主线程的控制器类,我们使用了QueuedConnection,以确保处理完成的

回调在主线程的上下文中安全地执行。

通过这些例子,我们可以看到,正确使用信号槽机制和ConnectionType参数对于确保Qt多线程应用的性能和稳定性至关重要。

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

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

相关文章

强化学习应用(四):基于Q-learning的物流配送路径规划研究(提供Python代码)

一、Q-learning算法简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于马尔可夫决策过程&#xff08;MDP&#xff09;的问题。它通过学习一个值函数来指导智能体在环境中做出决策&#xff0c;以最大化累积奖励。 Q-learning算法的核心思想是使用一个Q值函数来估计每…

边缘计算:挑战与机遇并存

边缘计算&#xff1a;挑战与机遇并存 在数字化时代&#xff0c;数据成为了驱动创新和经济增长的关键要素。然而&#xff0c;随着数据的不断增长&#xff0c;传统的集中式计算模式已经难以满足实时处理和分析的需求。边缘计算作为一种新兴的计算模式&#xff0c;通过将数据处理…

el-table 可编辑表格大数据渲染性能优化

背景与分析 可编辑表格&#xff1a;是指表格单元格是一个form表单元素&#xff0c;或者有可能会变成表单元素。 1、不可分页的表格&#xff0c;大数据渲染 当数据量足够大时&#xff0c;比如说1000条数据&#xff0c;页面渲染就会卡死&#xff0c;需要卡5s到10s&#xff0c;才…

BC7 缩短二进制

描述 我们处理的整数通常用十进制表示&#xff0c;在计算机内存中是以二进制补码形式存储&#xff0c;但通常二进制表示的整数比较长&#xff0c;为了便于在程序设计过程中理解和处理数据&#xff0c;通常采用八进制和十六进制&#xff0c;缩短了二进制补码表示的整数&#xf…

助力工业园区作业违规行为检测预警,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建工业园区场景下作业人员违规行为检测识别系统

在很多工业园区生产作业场景下保障合规合法进行作业生产操作&#xff0c;对于保护工人生命安全降低安全隐患有着非常重要的作用&#xff0c;但是往往在实际的作业生产中&#xff0c;因为一个安全观念的淡薄或者是粗心大意&#xff0c;对于纪律约束等意思薄弱&#xff0c;导致在…

Java Stream简化代码

使用原始流以获得更好的性能 使用 int、long 和 double 等基本类型时&#xff0c;请使用IntStream、LongStream 和 DoubleStream 等基本流&#xff0c;而不是 Integer、Long 和 Double 等装箱类型流。原始流可以通过避免装箱和拆箱的成本来提供更好的性能。 var array new i…

maven镜像源设置aliyun提升下载速度

一、打开pom.xml project下在添加 <repositories><repository><id>aliyunmaven</id><name>aliyun</name><url>https://maven.aliyun.com/repository/public</url></repository><repository><id>central2&l…

分布形态的度量_峰度系数的探讨

集中趋势和离散程度是数据分布的两个重要特征,但要全面了解数据分布的特点&#xff0c;还应掌握数据分布的形态。 描述数据分布形态的度量有偏度系数和峰度系数, 其中偏度系数描述数据的对称性,峰度系数描述与正态分布的偏离程度。 峰度系数反映分布峰的尖峭程度的重要指标. 当…

Leetcode 第 380 场周赛 Problem C 价值和小于等于 K 的最大数字(Java + 二分答案 + 规律)

文章目录 题目思路Java 二分答案 规律第 1 步&#xff1a;第 2 步&#xff1a;第 3 步&#xff1a;第 4 步&#xff1a; 复杂度Code 题目 Problem: 100160. 价值和小于等于 K 的最大数字给你一个整数 k 和一个整数 x 。令 s 为整数 num 的下标从 1 开始的二进制表示。我们说…

【ESP32接入语言大模型之智谱清言】

1. 智谱清言 讲解视频&#xff1a; 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。智谱清言作为千亿参数对话模型 基于ChatGLM2模型开发&#xff0c;支持多轮对话&#xff0c;具备内容创作、信息归纳总结等能力。可以快速注册体验中国版…

远程开发之vscode端口转发

远程开发之vscode端口转发 涉及的软件forwarded port 通过端口转发&#xff0c;实现在本地电脑上访问远程服务器上的内网的服务。 涉及的软件 vscode、ssh forwarded port 在ports界面中的port字段&#xff0c;填需要转发的IP:PORT&#xff0c;即可转发远程服务器中的内网端…

增强FAQ搜索引擎:发挥Elasticsearch中KNN的威力

英文原文地址&#xff1a;https://medium.com/nerd-for-tech/enhancing-faq-search-engines-harnessing-the-power-of-knn-in-elasticsearch-76076f670580 增强FAQ搜索引擎&#xff1a;发挥Elasticsearch中KNN的威力 2023 年 10 月 21 日 在一个快速准确的信息检索至关重要的…

探索C语言1:冷知识一瞥

C语言&#xff0c;作为一门古老而强大的编程语言&#xff0c;深藏着许多令人惊奇的冷知识。在这篇博客中&#xff0c;我们将一窥C语言的一些不太为人熟知的特性和概念&#xff0c;为你揭示这门编程语言的深奥之处。 字符串数组与指针的巧妙结合 在C语言中&#xff0c;字符串经…

基于MOD02/MYD02获得亮度温度再转冰温

用HEG处理MOD02/MYD02,提取里面的EV_1KM_Emissive波段,band为11和12(其实就是band 31和32)。注意这里的band和output dile type 1. 获得之后,转辐射亮度。 参考:https://www.cnblogs.com/enviidl/p/16539422.html radiance_scales,和radiance_offset这两项参数代表波段…

【生存技能】git操作

先下载git https://git-scm.com/downloads 我这里是win64&#xff0c;下载了相应的直接安装版本 64-bit Git for Windows Setup 打开git bash 设置用户名和邮箱 查看设置的配置信息 获取本地仓库 在git bash或powershell执行git init&#xff0c;初始化当前目录成为git仓库…

LeetCode讲解篇之216. 组合总和 III

文章目录 题目描述题解思路题解代码 题目描述 题解思路 使用递归回溯算法&#xff0c;当选择数字num后&#xff0c;在去选择大于num的合法数字&#xff0c;计算过程中的数字和&#xff0c;直到选择了k次&#xff0c;如果数组和等于n则加入结果集 从1开始选择数字&#xff0c;直…

ubuntu 2022.04 安装vcs2018和verdi2018

主要参考网站朋友们的作业。 安装时参考&#xff1a; ubuntu18.04安装vcs、verdi2018_ubuntu安装vcs-CSDN博客https://blog.csdn.net/qq_24287711/article/details/130017583 编译时参考&#xff1a; 【ASIC】VCS报Error-[VCS_COM_UNE] Cannot find VCS compiler解决方法_e…

平凡之路_2023年

平凡之路总结 思路总结&#xff0c;以XMIND 为形式&#xff0c;构建思维大厦&#xff0c;蛰伏与积累&#xff0c;下面补充对XMIND的描述 内功修炼问题意识&#xff08;输入&#xff09;与结构化思维&#xff08;输出&#xff09; – 同如何成为一个领域的专家 2024.1.14 最大的…

VCG 基于连通性网格面片聚类

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里的思路其实与点云的欧式聚类非常类似,区别在于点云的欧式聚类是通过搜索半径对点云进行聚类,至于基于连通性网格面片聚类则是通过面片的邻近关系对面片进行聚类,大致的过程与欧式聚类是相同的: 首先,需要指…

ant design vue createFromIconfontCN中的scriptUrl引入本地文件方案

背景说明&#xff1a;本项目使用vue 3&#xff0c;ant design vue v5&#xff0c;vite 构建。 本篇博客实现ant design vue中提供的createFromIconfontCN方法引入本地文件的方案。 官方文档如下&#xff1a; import { createFromIconfontCN } from ant-design/icons-vue; imp…