movetoThread应用的注意点

news2024/11/25 21:21:52

分析

官网的说明:

void QObject::moveToThread(QThread *targetThread)

Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.

To move an object to the main thread, use QApplication::instance() to
retrieve a pointer to the current application, and then use
QApplication::thread() to retrieve the thread in which the application
lives. For example:

myObject->moveToThread(QApplication::instance()->thread());

If targetThread is zero, all event processing for this object and its
children stops.

Note that all active timers for the object will be reset. The timers
are first stopped in the current thread and restarted (with the same
interval) in the targetThread. As a result, constantly moving an
object between threads can postpone timer events indefinitely.

A QEvent::ThreadChange event is sent to this object just before the
thread affinity is changed. You can handle this event to perform any
special processing. Note that any new events that are posted to this
object will be handled in the targetThread.

Warning: This function is not thread-safe; the current thread must be
same as the current thread affinity. In other words, this function can
only “push” an object from the current thread to another thread, it
cannot “pull” an object from any arbitrary thread to the current
thread.

其中关键的一句话:

Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.

这一句话的理解:
1、对象的构造函数不但不能用父类,父类的其它东西也是不行的
2、改变线程的关联,针对对象和它的孩子们,但是,如果不是孩子的new是不行的

示例1

改变线程的关联,针对对象和它的孩子们,但是,如果不是孩子的new是不行的。
如下图所示:
在这里插入图片描述

对象里面单独的new的变量是移不到目标线程当中去的,除非是作为孩子的节点。
controll的代码:

#include "controller.h"

Controller::Controller(QObject *parent) : QObject(parent)
{
  QString name = "thread1";
  Worker *worker = new Worker(name);
  m_pWorkerThread = new QThread();
  worker->moveToThread(m_pWorkerThread);
  connect(m_pWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
  connect(this, &Controller::operate, worker, &Worker::doWork);
   connect(this, &Controller::signalsBegin, worker, &Worker::onBegin);
  connect(worker, &Worker::resultReady, this, &Controller::handleResults);
  m_pWorkerThread->start();
}

Controller::~Controller()
{
  m_pWorkerThread->quit();
  m_pWorkerThread->wait();
}

void Controller::beginOperate()
{
    QString str = "begin";
    emit operate(str);
}

void Controller::begin()
{
    emit signalsBegin();
}

void Controller::handleResults(const QString &str)
{
   qDebug("enter function Controller::handleResults str=%s", str.toStdString().c_str());
   QThread *currentThread = QThread::currentThread();
   qDebug("exit function Controller::handleResults currentThread=%p", currentThread);
}

worker类的代码:

Worker::Worker(QString name, QObject *parent) : QObject(parent)
{
   qDebug("name=%s", name.toStdString().c_str());
   m_name = name;
   m_pTimer = new QTimer();
   m_pTimer->setInterval(1000);
}

void Worker::doWork(const QString &parameter)
{
 qDebug("enter function Worker::doWork parameter=%s", parameter.toStdString().c_str());
 QString result;
 /* ... here is the expensive or blocking operation ... */
 result = "executing";
 emit resultReady(result);
 QThread *currentThread = QThread::currentThread();
 qDebug("exit function Worker::doWork currentThread=%p", currentThread);
}

void Worker::onBegin()
{
    m_pTimer->start();
}

主函数:

#include <QCoreApplication>
#include "controller.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    Controller *controller = new Controller();
    controller->beginOperate();
    controller->begin();
    return a.exec();
}

上面的问题就是:
controller->begin()这一句导致的问题,这一句调用了:m_pTimer->start();
而成员变量m_pTimer是在主线程创建的,而非在子线程创建的,所以报上面的错。
由此可见:movetoThread()函数,只是移动了非new的成员变量与子对象,也就是未移动非子对象的new变量。
代码更改如下就可以了:

Worker::Worker(QString name, QObject *parent) : QObject(parent)
{
   qDebug("name=%s", name.toStdString().c_str());
   m_name = name;
   m_pTimer = new QTimer(this);
   m_pTimer->setInterval(1000);
}

就是QTimer()改成了QTimer(this);

总结

这个东西怎么说呢?movetoThread()函数,只是移动了非new的成员变量与子对象,也就是未移动非子对象的new变量,在QT中变量不能跨线程,所以跨线程的变量都会报错,有的报:
Cannot create children for a parent that is in a different thread.
这一个错误不需要加this,因为,this是主线程的this,去掉this即可解决问题。
QObject::startTimer: Timers cannot be started from another thread
这一个错误,需要加this,因为this是目标线程的this,加了this,Timers也移到目标线程了,这样就在一个线程中了。
其本质是一样的就是,变量跨线程(父与子跨线程也是不允许的,实质也是变量跨线程)
未moveToThread时是这样:

在这里插入图片描述

moveToThread之后是这样:
在这里插入图片描述

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

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

相关文章

流动微管反应器的精密压力控制解决方案

摘要&#xff1a;针对目前连续流反应器或微反应器压力控制中存在手动背压阀控制不准确、电动或气动背压阀响应速度太慢、无法适应不同压力控制范围和控制精度要求、以及耐腐蚀和耐摩擦性能较差等诸多问题&#xff0c;本文提出了相应的解决方案。解决方案的核心是分别采用了低压…

装配式从上世纪就开始了?到现在与BIM还干了这件大事!

​大家好&#xff0c;这里是建模助手。 说起装配式&#xff0c;相信各位都不会陌生。在我国传统建筑业资源浪费率高、污染重而饱受诟病的背景下&#xff0c;施工污染少、建造速度快、资源利用率高的装配式越来越受社会关注。 除了一些常规化的特点&#xff0c;如&#xff1a;…

4.2.2 基础指令的操作

显示日期与时间的指令&#xff1a; date 显示日历的指令&#xff1a; cal 简单好用的计算机&#xff1a; bc 1. 显示日期的指令&#xff1a; date 如果在命令行中想要知道目前Linux系统的时间&#xff0c;那么就直接在命令行界面输入date即可显示&#xff1a; [dmtsaistud…

小程序开发的优点和挑战:全面解析

小程序开发的优点是什么&#xff1f; 对于许多人来说&#xff0c;小程序的出现并没有给他们带来太多惊喜。然而&#xff0c;在过去的几年里&#xff0c;微信一直在努力成为更具影响力的社交平台&#xff0c;并且对于小程序开发的需求也在不断增加。随着小程序应用程序在其生态…

Spring Boot 属性加载原理解析

基于Spring Boot 3.1.0 系列文章 Spring Boot 源码阅读初始化环境搭建Spring Boot 框架整体启动流程详解Spring Boot 系统初始化器详解Spring Boot 监听器详解Spring Boot banner详解Spring Boot 属性配置解析Spring Boot 属性加载原理解析 在《Spring Boot 框架整体启动流程详…

MAYA柔体与弹簧一起使用 6个例子

例子2 Q弹 隐藏物体设置移动动画 例子 3 柔体和粒子 例子4 坑的反弹 例子5 例子6

021+limou+C语言内存管理

0.在Linux下验证C语言地址空间排布 这里是limou3434的博文系列。接下来&#xff0c;我会带您了解在C语言程序视角下的内存分布&#xff0c;会涉及到一点操作系统的知识&#xff0c;但是不多&#xff0c;您无需担忧。 注意&#xff1a;只能在Linux下验证&#xff0c;因为Windo…

如何在客户验收环节搞垮一个项目,大佬是有一套方法的

通过产品、UI、开发、测试撸起袖子加油干&#xff0c;经历需求、设计、研发、测试层层关卡终于进入到了期待已久的客户验收环节。在项目的尾声&#xff0c;连空气里都充满了快活的气氛。 而励志要搞垮项目的大佬心里就不爽了“小样儿&#xff0c;你们认为你们就赢了吗&#xf…

Nginx的安装和配置

下载 访问官网&#xff1a;https://nginx.org/ 点击最新的版本下载&#xff0c; 进入详情页&#xff0c;选择下载任意版本 解压编译安装 tar zxvf nginx-1.22.1.tar.gz解压之后得到文件夹 nginx-1.22 安装之前保证使用的工具和库存在 # 安装gcc yum install -y gcc # 安装…

STM32开发——串口通讯(第2篇)——WIFI(Esp8266)

目录 1.ESP8266 作为设备 2.ESP8266作为服务器 注意&#xff1a;1.在中断中一般不直接在中断服务函数里处理数据&#xff0c;而是在收到数据后直接丢给队列&#xff0c;再处理数据&#xff1b; 2.在中断服务函数里尽量减少使用延时函数及打印函数。 1.ESP8266 作为设备 1.1…

mongo副本集的一些操作

开启副本集 修改配置文件/etc/mongod.conf replication:replSetName: main重启mongod相关服务systemctl restart mongod 注意:每个在副本集中的成员&#xff0c;无论主副replSetName都一样&#xff0c;表示一个副本集的名称 如果添加的节点的replSetName和主节点不一致&…

退出卸载企业奇安信360

一般退出&卸载企业奇安信需要密码&#xff0c;然后我们又都不知道密码是多少的情况下怎么退出奇安信呢 1.打开奇安信的设置 2.找到 "防护中心"--"自我保护" 然后点击确定 3.找到奇安信的安装目录 找到"D:\奇安信\360Safe\EntClient\conf"下面…

python带你获取TripAdvisor旅游景点的真实评价

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 猫途鹰&#xff08;TripAdvisor&#xff09;是一个旅游点评网站&#xff0c; 如果您想要爬取该网站的数据&#xff0c;需要了解该网站的访问规则和爬取限制。 所使用软件工具&#xff1a; python 3.8 运行代码 pycha…

【PTA】温故知新模拟题

目录 L1-2 日期格式化 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 代码&#xff1a; L1-4 心理阴影面积 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; 代码&#xff1a; 7-3…

『论文精读』Vision Transformer(VIT)论文解读

『论文精读』Vision Transformer(VIT)论文解读 文章目录 一. 简介二. 模型架构2.1. 关于image presentation2.2. 关于positional encoding2.3. 关于CNNTransformer2.4. 关于输入图片大小 三. 实验部分3.1. 数据集3.2. 模型及变体3.3. 实验结果3.4. 模型可视化 参考文献 论文下…

CSS3_03:各种卡券优惠券模板制作,开箱即用,学得会,用得着

本文首发于微信公众号&#xff1a;布依前端 微信号&#xff1a;qny-1009 转载请注明出处 原创不易&#xff0c;觉得有用的话&#xff0c;多转发点赞支持 作为前端开发者&#xff0c;经常碰到不规则元素需求&#xff0c;尤其是购物类的优惠券&#xff0c;元素长相怪异&#xff0…

looks调色插件 Red Giant Magic Bullet Looks for Mac

Magic Bullet Looks for Mac版是一款looks调色插件&#xff0c;提供强大的外观和色彩校正功能&#xff0c;无论是对初学者还是影视专业制作人员&#xff0c;从冷酷惊艳的的动作场面到红色&#xff0c;暖色的浪漫色调&#xff0c;都可以帮助快速的完成&#xff0c;满足用户的所有…

LabVIEW开发基于Web数字图像处理

LabVIEW开发基于Web数字图像处理 数字图像处理已在各个领域找到了应用&#xff0c;并已成为一个高度活跃的研究领域。实际实施和实验在教育和研究活动中起着不可或缺的作用。为了方便快捷地实施数字图像处理操作&#xff0c;设计了一个先进的基于Web的数字图像处理虚拟实验室&…

vue3中引入tailwingcss

1、安装依赖 cnpm i -D tailwindcss postcss autoprefixer 2、安装完成后&#xff0c;创建tailwind.config.js 和 postcss.config.js配置文件&#xff0c;继续再控制台输入命令如下&#xff1a; npx tailwindcss init -P 3、修改tailwind.config.js content: ["./ind…

<Linux> 进程

文章目录 进程基本概念描述进程-PCBtask_struct-PCB的一种task_ struct内容分类 组织进程查看进程通过系统调用获取进程标示符fork创建子进程进程状态操作系统原理进程状态linux进程状态 优先级基本概念查看系统进程PRI and NI查看进程优先级的命令其他概念 环境变量基本概念常…