【Threads and QObjects,Thread-Support in Qt Modules】线程和QObjects,Qt模块中的线程支持

这篇具有很好参考价值的文章主要介绍了【Threads and QObjects,Thread-Support in Qt Modules】线程和QObjects,Qt模块中的线程支持。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Threads and QObjects

Threads 继承了 QObjects类。它发出信号来指示线程已开始执行或已完成执行,并提供一些槽函数。
更有趣的是,QObjects可以在多个线程中使用,发出调用其他线程中槽的信号,并将事件发布到“live”在其他线程中的对象。这是可能的,因为每个线程都允许有自己的事件循环。

QObject Reentrancy QObject的重入

QObject是可重入的。它的大多数非GUI子类,如QTimer、QTcpSocket、QUdpSocket和QProcess,也是可重入的,因此可以同时从多个线程使用这些类。请注意,这些类被设计为在单个线程中创建和使用;不能保证在一个线程中创建对象并从另一个线程调用其函数。有三个限制需要注意:
1、QObject的子对象必须始终在创建父对象的线程中创建。这意味着,除其他外,永远不应该将QThread对象(This)作为在线程中创建的对象的父对象传递(因为QThread物体本身是在另一个线程中创建)。
2、事件驱动的对象只能在单个线程中使用。具体地,这适用于定时器机制和网络模块。例如,不能在不是对象线程的线程中启动计时器或连接套接字。
3、删除QThread之前,必须确保删除在线程中创建的所有对象。这可以通过在run()实现中的堆栈上创建对象来轻松完成。
尽管QObject是可重入的,但GUI类,尤其是QWidget及其所有子类,是不可重入。它们只能从主线程使用。如前所述,还必须从该线程调用QCoreApplication::exec()。在实践中,通过将耗时的操作放在单独的工作线程中,并在工作线程完成时在主线程的屏幕上显示结果,可以很容易地解决在主线程以外的其他线程中使用GUI类的不可能性。这是用于实现Mandelbrot示例Blocking Fortune客户端示例的方法。
通常,不支持在QApplication之前创建QObjects,这可能会导致退出时出现奇怪的崩溃,具体取决于平台。这意味着也不支持QObject的静态实例。一个结构合理的单线程或多线程应用程序应该使QApplication成为第一个创建的和最后一个销毁的QObject。

Per-Thread Event Loop 每线程事件循环

每个线程都可以有自己的事件循环。初始线程使用QCoreApplication::exec()启动其事件循环,或者对于单对话框GUI应用程序,有时使用QDialog::exec()。其他线程可以使用QThread::exec()启动事件循环。与QCoreApplication一样,QThread提供了一个exit(int)函数和一个quit()槽。
线程中的事件循环使线程可以使用某些需要事件循环的非GUI Qt类(如QTimer、QTcpSocket和QProcess)。它还可以将来自任何线程的信号连接到特定线程的插槽。这将在下面的“跨线程的信号和插槽”部分中进行更详细的解释。
【Threads and QObjects,Thread-Support in Qt Modules】线程和QObjects,Qt模块中的线程支持,QT,qt,开发语言
QObject实例被认为存在于创建它的线程中。到该对象的事件由该线程的事件循环调度。使用QObject::thread()可以获得QObject所在的线程。
QObject::moveToThread()函数更改对象及其子对象的线程相关性(如果对象有父对象,则不能移动该对象)。
从拥有QObject的线程以外的线程调用delete(或以其他方式访问该对象)是不安全的,除非您保证该对象当时没有处理事件。改为使用QObject::deleteLater(),将发布一个DeferredDelete事件,对象线程的事件循环最终将接收该事件。默认情况下,拥有QObject的线程是创建QOObject的线程,但不是在调用QObject::moveToThread()之后。
如果没有事件循环正在运行,则不会将事件传递到对象。例如,如果在线程中创建一个QTimer对象,但从不调用exec(),则QTimer将永远不会发出其timeout()信号。调用deleteLater()也不起作用。(这些限制也适用于主线程。)
您可以使用线程安全函数QCoreApplication::postEvent()随时手动将事件发布到任何线程中的任何对象。事件将由创建对象的线程的事件循环自动调度。
所有线程都支持事件筛选器,但有一个限制,即监视对象必须与被监视对象位于同一线程中。类似地,QCoreApplication::sendEvent()(与postEvent()不同)只能用于将事件调度到调用函数的线程中的对象。

Accessing QObject Subclasses from Other Threads从其他线程访问QObject子类

QObject及其所有子类都不是线程安全的。这包括整个事件传递系统。重要的是要记住,当您从另一个线程访问对象时,事件循环可能会将事件传递到您的QObject子类。
如果您正在调用一个不在当前线程中的QObject子类上的函数,并且该对象可能会接收事件,则必须使用互斥锁保护对QObject个子类内部数据的所有访问;否则,您可能会遇到崩溃或其他不希望的行为。
与其他对象一样,QThread对象位于创建对象的线程中,而不是在调用QThread::run()时创建的线程中。在QThread子类中提供槽通常是不安全的,除非使用互斥体保护成员变量。
另一方面,您可以安全地从QThread::run()实现中发出信号,因为信号发射是线程安全的。

Signals and Slots Across Threads跨线程的信号和插槽

Qt支持以下信号槽连接类型:
自动连接(默认)如果信号是在接收对象具有关联性的线程中发出的,则行为与直接连接相同。否则,行为与排队连接相同。
直接连接发出信号时,会立即调用槽。槽在发射器的线程中执行,而发射器的线程不一定是接收器的线程。
排队连接当控制返回到接收器线程的事件循环时,将调用槽。槽在接收器的线程中执行。
阻塞排队连接调用槽时与调用排队连接时一样,但当前线程会阻塞,直到槽返回为止。注意:使用此类型连接同一线程中的对象将导致死锁。
唯一连接此行为与自动连接相同,但只有在不复制现有连接的情况下才能建立连接。即,如果同一信号已经连接到同一对对象的同一插槽,则不进行连接,connect()返回false。

可以通过向connect()传递额外的参数来指定连接类型。请注意,如果事件循环在接收方的线程中运行,则在发送方和接收方位于不同线程中时使用直接连接是不安全的,原因与调用位于另一个线程中的对象上的任何函数是不安全。
QObject::connect()本身是线程安全的。
Mandelbrot示例使用排队连接在工作线程和主线程之间进行通信。为了避免冻结主线程的事件循环(以及应用程序的用户界面),所有Mandelbrot分形计算都在一个单独的工作线程中完成。渲染完分形后,线程会发出一个信号。
类似地,Blocking Fortune客户端示例使用单独的线程与TCP服务器异步通信。

Mandelbrot示例和Blocking Fortune客户端示例 查看这篇博客。

Thread-Support in Qt Modules Qt模块中的线程支持

线程和SQL模块

连接只能在创建它的线程内使用。不支持在线程之间移动连接或从其他线程创建查询。
此外,QSqlDrivers使用的第三方库可能会对在多线程程序中使用SQL模块施加进一步的限制。

在线程绘画

QPainter可以在线程中用于在QImage、QPrinter和QPicture绘画设备上绘画。不支持在QPixmap和QWidget上绘制。在macOS上,如果从GUI线程外部打印,则不会显示自动进度对话框。
任何数量的线程都可以在任何给定的时间进行绘制,但是一次只能在给定的绘制设备上绘制一个线程。换言之,如果两条线程分别绘制在不同的QImage上,则两条线程可以同时绘制,但这两条线程不能同时绘制在同一QImage上。

线程与富文本处理

QTextDocument、QTextCursor和所有相关的类都是可重入的。
请注意,在GUI线程中创建的QTextDocument实例可能包含QPixmap图像资源。使用QTextDocument::clone()创建文档的副本,并将副本传递给另一个线程进行进一步处理(如打印)。

线程和SVG模块

QtSvg模块中的QSvgGenerator和QSvgRenderer类是可重入的。

线程和隐含共享类

Qt对其许多值类使用了一种称为隐式共享的优化,尤其是QImage和QString。从Qt4开始,隐式共享类可以像任何其他值类一样安全地跨线程复制。它们是完全可重入的。隐性共享实际上是隐性的。
在许多人看来,由于引用计数的典型方式,隐式共享和多线程是不兼容的概念。然而,Qt使用原子引用计数来确保共享数据的完整性,避免引用计数器的潜在损坏。
请注意,原子引用计数不能保证线程安全。在线程之间共享隐式共享类的实例时,应使用适当的锁定。这是对所有可重入类的相同要求,无论是否共享。然而,原子引用计数确实保证了在隐式共享类的本地实例上工作的线程是安全的。我们建议使用信号和插槽在线程之间传递数据,因为这可以在不需要任何显式锁定的情况下完成。
综上所述,Qt4中的隐式共享类实际上是隐式共享的。即使在多线程应用程序中,也可以安全地使用它们,就好像它们是普通的、非共享的、可重入的基于值的类一样。文章来源地址https://www.toymoban.com/news/detail-767584.html

到了这里,关于【Threads and QObjects,Thread-Support in Qt Modules】线程和QObjects,Qt模块中的线程支持的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (十一)【Jmeter】线程(Threads(Users))之jp@gc-Ultimate Thread Group

    简述 操作路径如下: 作用:提供了高级的线程组控制选项,支持更复杂的场景模拟。 配置:设置多种线程控制参数,如启动延迟、启动线程数、并发压测持续时间、关闭线程时间等。 使用场景:针对特定需求进行高级的并发访问模拟,如流量控制、延迟启动等。 优点:提

    2024年02月21日
    浏览(27)
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)

    简述 操作路径如下: 作用:通过逐步增加线程数来模拟用户并发访问。 配置:设置 This group will start 、 First,wait for 、 Then start 、 Next , add 等参数。 使用场景:模拟逐步增长的并发访问,观察应用程序的性能变化。 优点:适用于测试应用程序在逐步增加负载下的性能表现。

    2024年02月20日
    浏览(26)
  • Duplicate class com.amap.api.fence.DistrictItem found in modules location-6.2.0 and navi-3dmap-9.6.

    编译报错: Duplicate class com.amap.api.fence.DistrictItem found in modules location-6.2.0 (com.amap.api:location:6.2.0) and navi-3dmap-9.6.0_3dmap9.6.0 (com.amap.api:navi-3dmap:9.6.0_3dmap9.6.0) Duplicate class com.amap.api.fence.DistrictItem$1 found in modules location-6.2.0 (com.amap.api:location:6.2.0) and navi-3dmap-9.6.0_3dmap9.6.0 (com.amap.api:n

    2024年02月10日
    浏览(39)
  • (九)【Jmeter】线程(Threads(Users))之bzm-Free-Form Arrivals Thread Group

    简述 操作路径如下: 作用:支持自由形式的用户到达模式,具有更高的灵活性,与Arrivals Thread Group类似,不过是通过设置起始值、终止值和持续时间来达到压测目的。 配置:通过图形界面或脚本定义用户到达曲线。 使用场景:模拟复杂的用户到达模式,满足特定业务需求。

    2024年02月22日
    浏览(27)
  • Qt Installation and Setup in Windows with OpenCV ||Embedded Object Detection Project (Part 1)

    Qt Installation and Setup in Windows with OpenCV || Qt with OpenCV - Embedded Object Detection Project using Hikvision Industrial Camera (Part 1) I am documenting my experience in Qt development and hope that this article will be helpful to developers who are interested in learning and applying Qt. Don’t forget to click the “Follow” button to stay upda

    2024年02月21日
    浏览(26)
  • Qt Installation and Setup in Linux with OpenCV||Embedded Object Detection Project (Part 2)

    Qt Installation and Setup in Linux with OpenCV || Qt with OpenCV - Embedded Object Detection Project using Hikvision Industrial Camera (Part 2) Hi! This is my second post on Qt development about how to set up Qt with opencv in Linux System, compared with the last blog talking about Windows environment. Thanks for ur support and don’t forget to click the “

    2024年02月19日
    浏览(25)
  • WASI support in Go

    原文在这里。 由 Johan Brandhorst-Satzkorn, Julien Fabre, Damian Gryski, Evan Phoenix, and Achille Roussel 发布于 2023年9月13日 Go 1.21添加了一个新的端口,通过新的GOOS值wasip1来定位WASI预览1系统调用API。该端口建立在Go 1.11引入的现有WebAssembly端口的基础上。 WebAssembly(Wasm)是一种最初设计用于

    2024年02月08日
    浏览(32)
  • 关于Microsoft支持和恢复助手(Support and Recovery Assistant)卸载后无法再次安装的问题

    之前为了修复Office的问题下载了Microsoft 支持和恢复助手,后面觉得这玩意没什么用,就按照官方建议从控制面板直接卸载了。 但是!但是!!这种卸载方式并不彻底! ,等到我为了重装Visio又准备把它安装回来时,惊喜地发现安装程序提醒我已经安装过支持和恢复助手了(想

    2024年02月05日
    浏览(80)
  • ./node_modules/cache-loader/dist/cjs.js??ref--13-0!./node_modules/thread-loader/dist/cjs.js!

    Vue项目中执行打包命令 npm run build,出现以下报错 删除node_modules包后,重新装包,发现还是无法打包。 原因: 在原来镜像源的地址上,已经找不到这个插件了,没有装上,导致打包报错了。 解决方法: 1、更换镜像源 换成淘宝镜像源或者其他源,删除node_modules包后,再重新

    2024年02月15日
    浏览(26)
  • javafx应用程序线程异常Exception in thread “JavaFx Application Thread“

    前几天用javafx做小桌面应用程序出现了一个问题: 反复检查,最终确定报错的原因是UI刷新频率过快导致的 javafx提供了Platform.runLater用于解决该问题:  总结:需要高频调用方法使用Platform.runLater

    2024年02月10日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包