【Qt高阶】老Qt都不一定清楚的“QObject线程亲和性”【2023.08.13】

老Qt都不一定清楚的“线程亲和性”

与题目无关

  感觉自己还挺2,有粉丝点了那个契约者会给up发个鼓励的话,我还以为是人私信发的,都挨个感谢了,后来才意识到是系统自动发的。

  自上上期视频对Qt的槽函数执行在哪个线程做了分享之后,针对评论进行扩展学习,越发觉得自己对Qt底层不甚了解。尽管自己是从MFC转的Qt,对windows的消息有一定的技术储备,但是Qt做了封装之后,真就很多东西你要是光用的话很简单,但是深入下去搞懂Qt的源码,那就任重道远了。

  各平台对Qt信号槽的机制讲解结合我最近对源码的阅读,属实是粗浅。后期想针对Qt的信号槽这块的源码,从moc.exe编译出的cpp文件逐行代码讲起,将Qt信号槽讲透彻,其中必然涉及:d指针、事件循环、事件内核对象、窗口消息机制、以及很多帮助文档查不到的源码中存在的类。这就得整成成套的教程了,规划9月30号前把这块弄好。

简介

  本文继续围绕QThreadQTimer那个例子进行讲解。分析Qt槽函数执行在哪个线程,只不过这次拿官方的帮助文档背书。从手册中找解答。

一、回顾信号槽连接的connect函数

【Qt高阶】老Qt都不一定清楚的“QObject线程亲和性”【2023.08.13】_第1张图片

Qt信号槽连接的几种方式

  这是一个枚举值,描述了信号与槽的连接类型,连接类型会决定槽是被立即执行还是稍后执行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXLhL8l8-1691917098505)(F:\B站视频\Qt教程\Qt连接的几种方式.png)]

  自动连接:接收者与发送者在同一个线程构建,信号槽就会是直接连接,否则就是入队连接。连接类型具体是什么是当信号发出的时候才决定。

  直接连接:当信号发出的时候,槽被立即调用,槽执行在发信号的线程。

  入队连接:槽执行在接收者的线程。当控制返回接收者线程的事件循环时槽被调用。

  阻塞入队连接:与入队连接一样,除了发信号的线程会被阻塞直到槽返回阻塞才会失效。如果发信号和槽是在同一个线程使用这种连接会造成死锁。

  独占连接:一个信号只能连接到一个槽。可以与上面的四种组合使用。

二、本文的主角-“线程亲和性”

【Qt高阶】老Qt都不一定清楚的“QObject线程亲和性”【2023.08.13】_第2张图片

知识点:

  1. 一个QObject是存活在一个确定的线程的,这就叫线程的亲和性。
  2. 一个QObject接收到一个入队的信号或post出的事件,槽或者事件处理器会运行在QObject存活的那个线程。

如果一个对象没有线程亲和性,或所在的线程没有事件循环,则这个对象不会接收到信号和事件。

  1. 默认情况下,QObject执行在创建它的那个线程,可以通过thread() 查询它的线程亲和性。
  2. 线程亲和性可以被moveToThread()改变。
  3. 所有的QObject与他们的父是同一个线程。

如果两个对象处于不同的线程,setParent()会失败

moveToThread()会失败,如果QObject已经有父了。

如果QObject在run函数中创建,它们就不能变成QThread对象的孩子,因为QThread不存活在调用QThread::run的线程。

  1. 一个QObject的成员变量不会自动变成该类的子对象的,除非是构造函数传参,或者是调setParent。不指定父子关系,类的成员变量任然生存于老线程。

三、其实也不要以为Qt多牛逼,老马说过:“任何观念都可以从现实世界中找到其物质的“原型”

  线程亲和性这个技术也是有迹可循,参考下面的文章。

linux进程、线程与cpu的亲和性(affinity) - zhangwju - 博客园 (cnblogs.com)

你可能感兴趣的:(QT,qt,开发语言)