Qt扫盲-QObject对象和线程

news2024/9/23 1:34:47

QObject对象和线程

  • 一、概述
  • 二、QObjectReentrant性
  • 三、每个线程事件的循环
  • 四、从其他线程访问QObject的子类
  • 五、跨线程的信号和槽函数

一、概述

QThread继承QObject。QThread它发出信号来指示线程开始或结束执行,还提供了一些任务槽。

Qobject可以在多个线程中使用,发出信号调用其他线程中的槽函数,并将事件发送给“活动”在其他线程中的对象。这是可能的,因为每个线程都允许有自己的事件循环。

二、QObjectReentrant性

QObject是 Reentrant 的。什么是Reentrant 可以参考 Reentrant 。

QObject的大多数非gui子类,如QTimer、QTcpSocket、QUdpSocket和QProcess,也是Reentrant的,这使得从多个线程同时使用这些类成为可能。注意,这些类被设计为在单个线程中创建和使用;在一个线程中创建对象并在另一个线程中调用它的函数并不能保证有效。有三个约束需要注意。

  1. QObject的子对象必须始终在父对象创建的线程中创建。这意味着,除了其他事情之外,永远不应该将QThread对象(This)作为在线程中创建的对象的父对象(因为QThread对象本身是在另一个线程中创建的)。
  2. 事件驱动对象只能在单个线程中使用。具体来说,这适用于定时器机制和网络模块。例如,不能在非对象所属线程的线程中启动定时器或连接套接字。
  3. 在删除QThread之前,必须确保在线程中创建的所有对象都被删除。这可以通过在run()实现中在栈上创建对象来轻松实现。

虽然QObject是Reentrant的,但GUI类,尤其是QWidget及其所有子类,是不Reentrant的。它们只能在主线程中使用。如前所述,QCoreApplication::exec()也必须从该线程调用。

实际上,在主线程之外的其他线程中使用GUI类是不可能的,通过将耗时的操作放在单独的工作线程中,并在工作线程完成时在主线程的屏幕上显示结果,可以很容易地解决这个问题

一般来说,在QApplication之前创建qobject是不支持的,并且可能会在退出时导致奇怪的崩溃,这取决于平台。这意味着也不支持QObject的静态实例。一个结构合理的单线程或多线程应用程序应该让QApplication是第一个被创建,最后被销毁的QObject。

三、每个线程事件的循环

每个线程可以有自己的事件循环。初始线程使用QCoreApplication::exec()启动它的事件循环,或者对于单对话框GUI应用程序,有时使用QDialog::exec()。其他线程可以使用QThread::exec()启动事件循环。与QCoreApplication类似,QThread提供了一个exit(int)函数和一个quit()槽函数。

线程中的事件循环使得线程可以使用某些需要事件循环出现的非gui Qt类(如QTimer、QTcpSocket和QProcess)。它还可以将任何线程的信号连接到特定线程的槽函数。将在下面的跨线程信号和槽中更详细地解释。
在这里插入图片描述
QObject实例位于创建它的线程中。该对象的事件由该线程的事件循环分发。QObject所在的线程可以通过QObject::thread()获得。

QObject::moveToThread()函数更改对象及其子对象的线程亲和性(如果对象有父对象,则不能移动)。
如果不是从拥有该QObject的线程(或以其他方式访问该对象)上调用delete,则是不安全的,除非你保证该对象在那一刻没有处理事件。相反,使用QObject::deleteLater(),将发送一个DeferredDelete事件,对象线程的事件循环最终将接收该事件。默认情况下,拥有QObject的线程是创建QObject的线程,但在调用QObject::moveToThread()之后就不是这样了。

如果没有事件循环运行,事件就不会传递给对象。例如,如果您在线程中创建了一个QTimer对象,但从未调用exec(),那么QTimer将永远不会发出timeout()信号。调用deleteLater()也不能正常工作。(这些限制也适用于主线程。)
你可以使用线程安全函数QCoreApplication::postEvent()在任何时间手动向任何线程中的任何对象发送事件。事件将由创建对象的线程的事件循环自动分派。

所有线程都支持事件过滤器,但限制是监视对象必须与被监视对象在同一个线程中。类似地,QCoreApplication::sendEvent()(与postEvent()不同)只能用于将事件分发给函数调用所在线程中的对象。

四、从其他线程访问QObject的子类

QObject及其所有子类都不是线程安全的。这包括整个事件传递系统。重要的是要记住,当你从另一个线程访问对象时,事件循环可能会将事件传递给你的QObject子类。

如果在不在当前线程中的QObject子类上调用函数,并且该对象可能会接收事件,则必须使用互斥量保护对QObject子类内部数据的所有访问;否则,您可能会遇到崩溃或其他不希望出现的行为。

与其他对象一样,QThread对象存在于创建对象的线程中——而不是在调用QThread::run()时创建的线程中。在你的QThread子类中提供槽函数通常是不安全的,除非你用互斥量保护成员变量。
另一方面,你可以安全地从QThread::run()实现中发射信号,因为信号发射是线程安全的。

五、跨线程的信号和槽函数

Qt支持以下信号槽连接类型。
信号槽函数的一个参数会指定跨线程之类的,也就是最后一个默认参数 Qt::ConnectionType

QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection)

参数选项及解释:

  • Auto Connection (默认):如果信号在接收对象具有父子关系的线程中发出,那么行为与直接连接相同。否则,行为与排队连接相同。”

  • Direct Connection:当信号发出时,立即调用槽函数。槽函数在发射器的线程中执行,而不一定是接收器的线程。

  • Queued Connection:当控制返回到接收方线程的事件循环时,调用槽函数。槽函数在接收者的线程中执行。

  • Blocking Queued Connection:排队连接与队列连接一样调用槽函数,但当前线程阻塞直到槽函数返回。
    注意:使用此类型连接同一线程中的对象将导致死锁。

  • Unique Connection:连接行为与自动连接相同,但只有在不复制现有连接时才建立连接。也就是说,如果同一个信号已经连接到同一对对象的同一个槽函数,那么连接就不会建立,connect()返回false。

连接类型可以通过给connect()传递一个额外的参数来指定。请注意,如果事件循环在接收方的线程中运行,那么当发送方和接收方处于不同的线程中时,使用直接连接是不安全的,原因与在另一个线程中的对象上调用任何函数都是不安全的。

QObject::connect()本身是线程安全的。

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

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

相关文章

L1-006 连续因子

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3567,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。 输入格式: 输入在一行中给出一…

Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式

selenium中有8种不错的元素定位方式,每个方式和应用场景都不一样,需要根据自己的使用情况来进行修改 这里写目录标题1.id定位2.CSS定位3.XPATH定位4.name定位5.class_name定位6.Link_Text定位7.PARTIAL_LINK_TEXT定位8.TAG_NAME定位总结目前selenium已经…

力扣SQL刷题

目录标题571. 给定数字的频率查询中位数574. 当选者608. 树节点612. 平面上的最近距离619. 只出现一次的最大数字571. 给定数字的频率查询中位数 题型:给出数值和对应频率,返回中位数 解答:分别升序和降序排列。中位数正序和倒序所处的位置都…

人工智能图片素材高清,机器人图片卡通 素材

1、做一个人工智能的ppt需要哪些素材 不能理解你的问题。ppt仅仅是一个做幻灯的软件,可以插入图片、动画、音乐、过场等幻灯的功能,还谈不上有人工智能的能力。人工智能需要有更为强大的类似人脑思维的能力,简单的说人工智能是可以思考的机器…

【HBase——陌陌海量存储案例】2. HBase表结构设计(中)

前言 本文是陌陌海量存储案例——HBase表结构设计(中),介绍ROWKEY设计原则、项目初始化。 4.5 ROWKEY设计原则 4.5.1 HBase官方的设计原则 避免使用递增行键/时序数据 如果ROWKEY设计的都是按照顺序递增(例如:时间…

信息论复习—差错控制编码

目录 差错控制编码的基本概念: 差错控制编码的主要类型和方式: 差错控制编码的主要类型: 差错控制方式: 简单的差错控制方法: 奇偶校验码: 重复码: 信道编码的基本概念和定理*: 信道编…

4 反向传播

文章目录问题提出计算图中的神经网络改进(激活函数)反向传播前馈计算反向传播pytorch当中的前馈与反馈Tensor张量课程代码课后作业课程来源: 链接课程内容部分来源(觉得归纳的非常好的): 链接以及&#xff…

MySQL中的运算符

目录 一.运算符 简介 算术运算符 比较运算法 逻辑运算符 位运算符 实例演示 一.运算符 简介 数据库中的表结构确立后,表中的数据代表的意义就已经确定。通过MySQL运算符进行运算,就可以获取到表结构以外的另一种数据。 例如,学生表中…

[数据结构笔记]二叉树初阶

基本知识 树 -节点的度:一个节点含有的子树的个数称为该节点的度; -叶节点或终端节点:度为0的节点称为叶节点; -非终端节点或分支节点:度不为0的节点; -父节点:若一个节点含有子节点&#xff…

Mybatis 通过接口实现 sql 执行原理解析

使用过 mybatis 框架的小伙伴们都知道,mybatis 是个半 orm 框架,通过写 mapper 接口就能自动实现数据库的增删改查,但是对其中的原理一知半解,接下来就让我们深入框架的底层一探究竟1、环境搭建首先引入 mybatis 的依赖&#xff0…

Consul服务注册与发现

目录 一、Consul简介 (一)官网 (二)特点 二、安装并运行Consul (一)官网安装说明 (二)下载 (三)使用开发模式启动 三、服务提供者 四、服务消费者 …

怎么压缩pdf文件?选对方法其实很简单!

相信许多人在使用设备的时候都会面对这样一个问题,那就是设备内存不足。仿佛不管我们多么努力的节省空间,总是会到头来遇到储存空间不足得难题,尤其是一些比较大的pdf文件,特别占据我们的设备内存,那么你知道怎么压缩p…

0128 Web API基本认知

作用使用JS去操作html和浏览器分类DOM(文档对象模型)BOM(浏览器对象模型)DOM是什么:Document Object Model-----文档对象模型,用来呈现以及与任意HTML或XML文档交互的API,浏览器提供的一套专门用…

【Linux】一文掌握Linux权限

环境:centos7,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹前言权限 一词相信大家都不陌生,与我们的生活密切相关。小区里的门禁制度、公司里的管理制度、学校里的校规规定、甚至是社交平台上的一些设置…

python 手机相机传感器信息计算

传感器信息计算 输入传感器尺寸以上已红米12pro为例 输入传感器尺寸 1/1.4英寸 0.7142857 输入像素2亿 200000000 得到以下结果 和宣传中的传感器信息一致 附源码 import sympyclass CMosInfo(object):"""传感器信息计算"""def __init__(…

C 程序设计教程(19)—— 数组和指针(二):字符数组与字符串

C 程序设计教程(19)—— 数组和指针(二):字符数组与字符串 该专栏主要介绍 C 语言的基本语法,作为《程序设计语言》课程的课件与参考资料,用于《程序设计语言》课程的教学,供入门级用…

word实用操作:几个关于录入和排版的小妙招

对于职场人来说,工作中使用Word早已成了习惯。而如何提高Word的技术,那简直是职场人一生都需要研究探索的课题。因此,今天小编将为大家分享几个实用的Word小技巧,这些技巧貌似不起眼,但是学会后,可以大大提…

如何查linux服务器的带宽占用?哪些进程占用带宽?

前言操作系统: Linux操作环境: Centos7 / ubuntulinux查看服务器带宽具体方法   一、使用speedtest-cli命令查看下载和上传最大流量值因为命令是python的,所以需要先下载一个python,用pip下载次命令;123yum -y insta…

七个 Vue 项目用得上的 JavaScript 库分享

文章目录前言一、vueuse二、vue-js-modal三、vue-wait四、good-table五、vue-notification六、tree select七、egjs-infinite grid总结前言 借助开源库加速 Vue 项目的开发进度是现代前端开发比较常见的方式,平常收集一些 JavaScript 库介绍,在遇到需要的…

上古神兵,先天至宝,Win11平台安装和配置NeoVim0.8.2编辑器搭建Python3开发环境(2023最新攻略)

毫无疑问,我们生活在编辑器的最好年代,Vim是仅在Vi之下的神级编辑器,而脱胎于Vim的NeoVim则是这个时代最好的编辑器,没有之一。异步支持、更好的内存管理、更快的渲染速度、更多的编辑命令,是大神Thiago de Arruda对开…