当前位置: 首页 > news >正文

qt之movetothread理解

基础概念

  • qt的下线程qthread,每个线程都有自己的事件循环exec。
  • 对象的线程上下文,每个对象都有自己的线程上下文,怎么理解呢,就是该对象在哪个线程创建,其线程上下文就是谁。
  • 每个qobject对象在创建时都有包含线程成员,threaddata,该成员的类型是QThreadData,该成员与qobject对象的父对象保持一致,若父对象不存在,则取当前线程的值为该成员赋值,详见源码如下:
QObject::QObject(QObject *parent): d_ptr(new QObjectPrivate)
{Q_D(QObject);d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();if (parent) {if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))parent = 0;setParent(parent);
}

 如上代码可以得出如下结论:

  • 当创建QObject时,在构造函数中会根据父对象的值进行赋值,规则是如果父对象存在,并且父对象下thread成员存在,则赋值给新创建的threadData成员;否则将当前多线程的线程数据赋值给该对象threadData成员。
void QObject::moveToThread(QThread *targetThread)
{Q_D(QObject);if (d->parent != 0) {qWarning("QObject::moveToThread: Cannot move objects with a parent");return;}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) : new QThreadData(0);if (d->threadData->thread == 0 && currentData == targetData) {// one exception to the rule: we allow moving objects with no thread affinity to the current threadcurrentData = d->threadData;} else if (d->threadData != currentData) {qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p)./n""Cannot move to target thread (%p)/n",currentData->thread, d->threadData->thread, targetData->thread);return;}
......

 通过如上代码可以看到movetothread的限制条件如下:

  1. 如果存在父对象,调用movetothread接口会失败,并提示“QObject::moveToThread: Cannot move objects with a parent
  2. 如果是该对象是QWidget或者其子类,不能调用movetothread,因为qwidget及其子类只能在主线程中。否则会产生“QObject::moveToThread: Widgets cannot be moved to a new thread”错误
  3. 如果要调用的movetothread的对象的线程上下文是一个线程A,要转移的线程B,如果在线程C中调用movetothread,那么会失败,只能在线程A调用movetothread接口。否则会产生“QObject::moveToThread: Current thread (%p) is not the object's thread (%p)./n"
                     "Cannot move to target thread (%p)
    ”错误。

movetothread的本质

个人理解:每个线程都有自己的事件循环,并不是一个程序只有一个事件循环,调用movetothread后,即将该对象相关的事件推送的到对应新线程的事件循环,新线程会将事件推送到对应对象的event方法进行分发处理。所以只有事件类型的才可以在新线程中执行(即只能通过信号槽机制来调用,因为跨线程信号槽机制会触发事件推送;在另外一个线程中通过函数调用的方式调用该对象的方法不会在新线程中执行,而是在调用线程执行)。

重点

movetothread是一种多线程的实现方式

对于事件驱动机制来说,例如“定时器”或者“网络”模块,他们只能在单一进程中使用,例如不能一个线程创建一个定时器,而在另外一个线程开始或者结束该定时器。这些操作都不可取。

http://www.lryc.cn/news/163704.html

相关文章:

  • 深入剖析:垃圾回收你真的了解吗?
  • ue5 物理场的应用
  • 移动零00
  • go初识iris框架(四) -框架设置操作
  • python基础语法(二)
  • 从本地到Gitee:一步步学习文件上传及解决常见报错问题
  • idea2018修改大小写提示(敏感)信息
  • Quartz.Net调度框架简介
  • HarmonyOS/OpenHarmony(Stage模型)应用开发组合手势(一)连续识别
  • Redis --- 位图
  • 自然语言处理-词向量模型-Word2Vec
  • List知识总结
  • 代码随想录day32
  • 2.8 PE结构:资源表详细解析
  • Python数据类型的相互转换
  • 阿里云云主机免费试用三个月
  • OpenHarmony 使用 ArkUI Inspector 分析布局
  • Axes3D绘制3d图不出图解决办法【Python】
  • Idea中 css 、js 压缩插件会自动生成xxx.min.css、xxx.min.js文件
  • win11无法加载文件,因为在此系统上禁止运行脚本
  • Spring Boot将声明日志步骤抽离出来做一个复用类
  • RabbitMQ实现数据库与ElasticSearch的数据同步和分享文件过期处理
  • PyCharm集成开发环境安装、启动与设置
  • 算法与设计分析--实验一
  • ElementUI浅尝辄止28:Dropdown 下拉菜单
  • jupyter 格式化与快捷键
  • Spring以及SpringBoot/SpringCloud注解
  • vim常用操作
  • Serverless Framework 亚马逊云(AWS)中国地区部署指南
  • 【Spring Cloud系统】- 轻量级高可用工具Keepalive详解