movetoThread应用的注意点

news/2024/11/23 2:30:55/

分析

官网的说明:

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.ppmy.cn/news/400050.html

相关文章

【北邮国院大三下】Intellectual Property Law 知识产权基础 Week4

北邮国院大三电商在读&#xff0c;随课程进行整理知识点。仅整理PPT和相关法条中相对重要的知识点&#xff0c;个人认为相对不重要的细小的知识点不列在其中。如有错误请指出。转载请注明出处&#xff0c;祝您学习愉快。 如需要pdf格式的文件请私信联系或微信联系 PRC是否inf…

专转本-常用电脑设备

显示设备 显卡 显卡主体 1.HDMI 2.VGA 3.DVI GPU 1.生产厂家 2.电压要求 3.对应型号 CRT

九联UNT401H主板2+8桌面蓝牙语音通刷固件

九联UNT401H主板28桌面蓝牙语音通刷固件 九联UNT401H-零配置版机顶盒开机后按遥控器设置键进入系统设置界面&#xff0c;遥控器均匀按下数字键782782323即可开启adb功能&#xff0c; 机顶盒刷机前在电脑上使用一键替换rec工具替换掉原机recovery文件&#xff0c; 然后再将下载…

YOGA27多维一体电脑,兼具出色外观与高端配置

在当今科技数码行业,用户更加关注产品的外观设计。各品牌厂商在提升配置的同时,也在外观设计上下足了功夫,比如最近的联想YOGA 27多维一体电脑就交上了一份令用户满意的答卷。为什么YOGA27能够吸引消费者关注?下面将一一揭晓。 首先,联想YOGA 27的双轨设计可随意变换产品形态,…

【Spring学习之生命周期】什么是生命周期?什么是作用域?了解六种作用域

前言&#xff1a; &#x1f49e;&#x1f49e;从前⾯的课程我们可以看出 Spring 是⽤来读取和存储 Bean&#xff0c;因此在 Spring 中 Bean 是最核⼼的操作资源&#xff0c;所以接下来我们深⼊学习⼀下 Bean 对象。 前路漫漫&#xff0c;希望大家坚持下去&#xff0c;不忘初心&…

联想r720自带杜比驱动下载_暑假追剧补习神器,联想M10 PLUS评测

迈入八月&#xff0c;暑假正当时。空调wifi西瓜&#xff0c;追剧游戏宅家&#xff0c;这样的日子的确很舒服&#xff0c;“假期不努力&#xff0c;开学徒伤悲”&#xff0c;姑且不说要报各种兴趣班&#xff0c;先把主科学好就刻不容缓。联想Tab M10 PLUS专门为小学到高中的同学…

电脑常用操作

文章目录 笔记本声音调大U盘问题U盘损坏U盘复制内存不够 快捷键关机开始Win R计算器控制面板 设置 Powershell远程桌面 笔记本声音调大 笔记本的右下角声音和播放器声音都调到最大之后声音还是很小。 控制面板-硬件和声音-声音-扬声器-均衡器&#xff1a;设置-现场。 U盘问题…

烽火HG680-J_Hi3798MV100_内有普通版和高安版-当贝桌面-卡刷强刷固件包

烽火HG680-J_Hi3798MV100_内有普通版和高安版-当贝桌面-卡刷强刷固件包-内有短接图和教程 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精…