QObject_thread

QObject::thread

QThread *QObject::thread()

返回对象所在的线程。

QThread *QObject::thread() const
{return d_func()->threadData.loadRelaxed()->thread.loadAcquire();
}

void QObject::moveToThread(QThread *targetThread)

将此对象及其孩子关联到targetThread线程,事件处理将在targetThread中继续进行,
在线程关联被改变之前QEvent::ThreadChange事件被发送给这个对象和其孩子对象。

注意:

  1. widget类型(继承QWidget的类)对象只能在主线程中,所以调用moveToThread无效。
  2. 如果对象有父对象,则不能移动该对象。
  3. 调用者必须与此对象在同一线程,除非此对象没有关联线程
  4. 该对象的计时器timer首先在当前线程中停止,然后在targetThread中重新启动(间隔相同)。因此,在线程之间不断移动对象会无限期地延迟计时器事件。
  5. 如果targetThread为nullptr,则此对象及其子对象的所有事件处理都将停止,因为它们不再与任何线程相关联。
使用样例:
int main()
{QThread *th = new QThread();myobject *obj1= new  myobject("boj1");obj1->connect(obj1,&myobject::signal1,obj1,&myobject::slot1);obj1->moveToThread(th);//调用在主线程与obj1同一线程//因为线程启动后才会执行事件循环,所以必须启动线程th->start();qDebug()<<"main QThreadid = "<<QThread::currentThreadId()<<",date="<<QDateTime::currentSecsSinceEpoch();emit obj1->signal1(111);return 0;
}
函数解读:
void QObject::moveToThread(QThread *targetThread)
{Q_D(QObject);//如果对象有父对象,则不能移动该对象。if (d->parent != nullptr) {qWarning("QObject::moveToThread: Cannot move objects with a parent");return;}//对象是widget类型的不能移动widget类型的只能在主线程中//继承QWidget的类都是widget类型//explicit QWidget(QWidget* parent = nullptr, Qt::WindowFlags);if (d->isWidget) {qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");return;}//调用此函数的所在线程,即当前线程QThreadData *currentData = QThreadData::current();//移动到的目标线程QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;//对象所在线程数据,QThreadData *thisThreadData = d->threadData.loadRelaxed();//如果对象没有关联线程,并且目标线程等于当前线程,可以移动if (!thisThreadData->thread.loadAcquire() && currentData == targetData){//我们允许将没有线程关联的对象移动到当前线程currentData = d->threadData;} else if (thisThreadData != currentData) {//只能在object所在的线程里面调用此函数qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n""Cannot move to target thread (%p)\n",currentData->thread.loadRelaxed(), thisThreadData->thread.loadRelaxed(), targetData ? targetData->thread.loadRelaxed() : nullptr);return;}// 移动前先发送QEvent::ThreadChange事件d->moveToThread_helper();if (!targetData)targetData = new QThreadData(0);//确保在我们移动这个对象时没有人添加/删除连接QMutexLocker l(signalSlotLock(this));QOrderedMutexLocker locker(&currentData->postEventList.mutex,&targetData->postEventList.mutex);// 保持currentData存活(因为我们已经锁定了它)currentData->ref();// 真正的移动对象d_func()->setThreadData_helper(currentData, targetData);locker.unlock();// now currentData can commit suicide if it wants tocurrentData->deref();
}void QObjectPrivate::moveToThread_helper()
{Q_Q(QObject);QEvent e(QEvent::ThreadChange);//sendEvent发送ThreadChange事件//因为sendEvent是同步调用,所以等对象处理完事件后,才能继续往下走QCoreApplication::sendEvent(q, &e);//给对象的所有孩子发送ThreadChange事件for (int i = 0; i < children.size(); ++i) {QObject *child = children.at(i);child->d_func()->moveToThread_helper();}
}void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
{for (int i = 0; i < currentData->postEventList.size(); ++i) {const QPostEvent &pe = currentData->postEventList.at(i);if (!pe.event)continue;if (pe.receiver == q) {//将此post事件移动到targetList中targetData->postEventList.addEvent(pe);const_cast<QPostEvent &>(pe).event = nullptr;++eventsMoved;}}//当前线程在调用moveToThread()后不应该恢复currentSenderConnectionData *cd = connections.loadRelaxed();if (cd) {if (cd->currentSender) {cd->currentSender->receiverDeleted();cd->currentSender = nullptr;}// 调整连接中的receiverThreadId值if (cd) {auto *c = cd->senders;while (c) {QObject *r = c->receiver.loadRelaxed();if (r) {Q_ASSERT(r == q);targetData->ref();QThreadData *old = c->receiverThreadData.loadRelaxed();if (old)old->deref();c->receiverThreadData.storeRelaxed(targetData);}c = c->next;}}}// 设置新线程数据targetData->ref();threadData.loadRelaxed()->deref();//同步其孩子到targetData线程//QObject的孩子肯定不是widget一类,所以可以直接移动不用判断for (int i = 0; i < children.size(); ++i) {QObject *child = children.at(i);child->d_func()->setThreadData_helper(currentData, targetData);}
}

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

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

相关文章

C++内存管理机制(侯捷)笔记2

C内存管理机制&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youtube: 侯捷-C内存管理机制 Github课程视频、PPT和源代码: https://github.com/ZachL1/Bilibili-plus 下面是第二讲allocator具体实…

11 双向链表

单链表的局限&#xff1a; 单链表的缺点&#xff1a;逆序访问单链表中的元素耗时大。&#xff08;时间复杂度&#xff1a;O&#xff09; 双向链表的定义 第0个节点【a1】的pre指针为NULL&#xff0c;要注意 插入操作&#xff1a; 删除操作&#xff1a; 初步实现双链表 代码&…

【Vue系列】Vue3快速构建项目,以及在已有代码情况首次打开如何初始化依赖项

欢迎来到《小5讲堂》 大家好&#xff0c;我是全栈小5。 这是是《前端》序列文章&#xff0c;每篇文章将以博主理解的角度展开讲解&#xff0c; 特别是针对知识点的概念进行叙说&#xff0c;大部分文章将会对这些概念进行实际例子验证&#xff0c;以此达到加深对知识点的理解和掌…

一天一个设计模式---适配器模式

概念 适配器模式是一种结构型设计模式&#xff0c;用于将一个类的接口转换成客户端所期望的另一个接口。它允许不兼容的接口之间进行协同工作&#xff0c;使得原本由于接口不匹配而无法合作的类能够一起工作。 具体内容 适配器模式主要包括以下几个要素&#xff1a; 目标接…

C 语言结构体和枚举完全指南:成员访问、字符串操作、枚举基础

访问结构体成员 要访问结构体的成员&#xff0c;请使用点语法 (.): // 创建名为 myStructure 的结构体 struct MyStructure {int myNum;char myLetter; };int main() {// 创建名为 s1 的 myStructure 的结构体变量struct MyStructure s1;// 为 s1 的成员分配值s1.myNum 13;s…

Miniconda Python解释器 Conda 包管理器 Pytorch

Miniconda Miniconda 是一个轻量级的 Anaconda 版本&#xff0c;它是一个用于管理 Python 环境和包的开源工具。Anaconda 是一个数据科学和机器学习的开发环境&#xff0c;它包含了许多常用的 Python 包和工具。 与 Anaconda 相比&#xff0c;Miniconda 的安装包更小&#xf…

VBA中类的解读及应用第八讲:实现定时器功能的自定义类事件

《VBA中类的解读及应用》教程【10165646】是我推出的第五套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。 类&#xff0c;是非常抽象的&#xff0c;更具研究的价值。随着我们学习、应用VBA的深入&#xff0…

Java中输入和输出处理(三)二进制篇

叮咚&#xff01;加油&#xff01;马上学完 读写二进制文件Data DataInputStream类 FilFeInputStream的子类 与FileInputStream类结合使用读取二进制文件 DataOutputStream类 FileOutputStream的子类 与FileOutputStream类结合使用写二进制文件 读写二进制代码 package 面…

vue实现-年、月、日、时、分、秒、星期?

一、文章引导 #mermaid-svg-nP4oT3Y4d6oaxUsg {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-nP4oT3Y4d6oaxUsg .error-icon{fill:#552222;}#mermaid-svg-nP4oT3Y4d6oaxUsg .error-text{fill:#552222;stroke:#55222…

Pangolin编译

文章目录 版本编译错误 版本 ubuntu 22 编译 # 复制选择版本&#xff08;ORB SLAM 需要的版本为0.6&#xff09; git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin/ git checkout v0.6# 编译 mkdir build && cd build cmake .. -DCMAKE_INS…

倍福(Bechhoff) CX8090嵌入式PC控制器开发没有想像中的那么难

笔者曾2023年初曾为云南阜外医院新风系统开发自动控制系统。医院所有新风设备和公区照明全部采用倍福嵌入式PC控制器实现智能控制。其中新风和供水计量通过CX8090实现控制&#xff1b;公区照明通过BC9050实现控制&#xff1b;并采用美国邦纳人机界面(THM035B&#xff09;实现远…

树形结构的窗口小部件

这段代码是一个使用Qt框架的C程序&#xff0c;实现了一个树形结构的窗口小部件&#xff08;TreeWidget&#xff09;。以下是主要的解释&#xff1a; #include "treewidget.h" #include "ui_treewidget.h"TreeWidget::TreeWidget(QWidget *parent) : QWidg…

DB2除法的小数位问题(四舍五入问题)以及其他常用的函数

DB2除法的小数位问题&#xff08;四舍五入问题&#xff09;以及其他常用的函数 1. DB2取第一条数据2. DB2 中指定值排序2.1 使用case when2.2 使用decode函数 3. 拼接函数4. 强制转换类型——cast函数5. DB2除法的小数位问题&#xff08;四舍五入问题&#xff09;5.1 关于round…

栈和排序.

给你一个1->n的排列和一个栈&#xff0c;入栈顺序给定 你要在不打乱入栈顺序的情况下&#xff0c;对数组进行从大到小排序 当无法完全排序时&#xff0c;请输出字典序最大的出栈序列 输入 第一行一个数n 第二行n个数&#xff0c;表示入栈的顺序&#xff0c;用空格隔开&…

three.js 关键帧动画

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div class"box-right"…

用汇编编写加解密函数

1.data段 data db "hello,sam" key db "key" dataLen dword ? endata byte 10 dup(0) dedata byte 10 dup(0) 2.Encryption&#xff08;加密&#xff09; Encryption procpush ebpmov ebp,esp;加密数据长度,循环次数mov ecx,sizeof data;寄存器不够用…

金和OA jc6 GetAttOut SQL注入漏洞复现

0x01 产品简介 金和OA协同办公管理系统软件(简称金和OA),本着简单、适用、高效的原则,贴合企事业单位的实际需求,实行通用化、标准化、智能化、人性化的产品设计,充分体现企事业单位规范管理、提高办公效率的核心思想,为用户提供一整套标准的办公自动化解决方案,以帮助…

方法 ‘NetWork.call()‘ 的签名与类 ‘Model‘ 中基方法的签名不匹配

方法 ‘NetWork.call()’ 的签名与类 ‘Model’ 中基方法的签名不匹配 这个错误通常出现在 TensorFlow 的 Keras 模型中&#xff0c;表示子类化的模型&#xff08;比如你的 NetWork 类&#xff09;在实现 call 方法时与基类 Model 中定义的 call 方法的签名不匹配。 在这里&am…

语义解析:如何基于SQL去实现自然语言与机器智能连接的桥梁

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 语义解析 定义 作用 语义解析的应用场景 场景一&#xff1a; 场景二&#xff1a; 总结语…

【LeetCode】winter vacation training

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb; 有效的字母异位词&#x…