Qt moveToThread

简介: Qt moveToThread

moveToThread位于QObject中,官方对此函数的解释如下:

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.


这个函数适合于QObject及其子类,并且QObject的父对象必须为空,否则移动到线程失败。移动成功后,将在目标线程中开启事件处理。

待移动到线程的Object

// 耗时操作具体执行的类
class Worker : public QObject
{
    Q_OBJECT
public:
    Worker(QObject* parent = 0);
    virtual ~Worker();
signals:
    void sglProgress(int val); // 进度信号,[0, 100],指示进度
    void sglFinished(); // 结束信号
public slots:
    // 开始执行耗时操作的槽函数,结束后调用deleteLater(),析构自己
    void start();
};

启动类

void FrmMain::sltWork()
{
    Worker* worker = new Worker(0); // parent 需为0
    // 连接耗时操作进度和完成信号对应的槽函数
    connect(worker, SIGNAL(sglProgress(int)), this, SLOT(sltProgress(int)));
    connect(worker, SIGNAL(sglFinished()), this, SLOT(sltFinished()));
    QThread* thread = new QThread(0); // 开启一个新线程
    worker->moveToThread(thread);
    // worker需在线程启动后开启,这也是耗时操作的start()函数是槽函数的原因
    connect(thread, SIGNAL(started()), worker, SLOT(start()));
    // 耗时操作完成后,线程退出
    connect(worker, SIGNAL(sglFinished()), thread, SLOT(quit()));
    // 特别说明(1),看后面详细说明
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    // 启动线程
    thread->start();
}

防止内存泄漏,需要使用deleteLater()函数析构thread,常见的一个bug是这样造成的

connect(worker, SIGNAL(sglFinished()), thread, SLOT(deleteLater()));

看上去好像也没什么,其实,会是一个很不稳定的因素,如果线程相对简单,可以很快quit掉,程序仿佛可以正常运行,而事实上并不总是这样,以为worker的sglFinished()信号同时连接了thread的quit()和deleteLater()两个槽函数,如果quit()还没执行完成时,就执行deleteLater(),会造成软件的崩,或者Destroyed while thread is still running这样的bug()。因此,sglFinished()信号连接了线程quit()函数,线程正常退出后,会释放finished()信号,然后由finished()信号连接线程的deleteLater()槽函数,会使线程安全的退出并析构。


参考:

1、Qt 多线程之QObject::moveToThread

2、简单说说对QT中moveToThread实现多线程操作的理解

3、Qt线程实现分析-moveToThread vs 继承

目录
相关文章
|
数据可视化
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Date/Time Edit的使用及说明
【Qt 学习笔记】Qt常用控件 | 输入类控件 | Date/Time Edit的使用及说明
1420 2
|
网络协议
Qt中的网络编程(Tcp和Udp)运用详解以及简单示范案例
Tcp和Udp是我们学习网络编程中经常接触到的两个通讯协议,在Qt也被Qt封装成了自己的库供我们调用,对于需要进行网络交互的项目中无疑是很重要的,希望这篇文章可以帮助到大家。 是关于Qt中TCP和UDP的基本使用和特点:
1746 7
|
存储 数据可视化 NoSQL
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
3435 0
Qt Creator的CDB调试器--使用技巧与解决调试很慢的心得,重点是Symbols Path设置
|
消息中间件 存储 安全
深入理解 Qt 信号槽:高效沟通的桥梁
深入理解 Qt 信号槽:高效沟通的桥梁
1240 1
|
存储 前端开发 开发者
scss概念及使用
【7月更文挑战第11天】
355 1
|
搜索推荐 数据采集
推荐个好用的云盘资源网站(搜索引擎)
推荐个好用的云盘资源网站(搜索引擎)
4984 0
推荐个好用的云盘资源网站(搜索引擎)
|
编解码 网络协议 C#
wpf下如何实现超低延迟的RTMP或RTSP播放
本文介绍在Windows平台上使用大牛直播SDK的SmartPlayer模块实现在WPF中播放RTMP/RTSP流的方法。通过设置回调函数并选择RGB32格式,可以直接处理视频帧数据进行显示。此外,也可利用PictureBox控件简化视频流的展示。文章提供了示例代码,展示了如何初始化播放器、开始及停止播放,并演示了同时播放两路不同分辨率流的效果及CPU占用情况。SmartPlayer支持多实例播放、多种视频与音频格式、软硬解码、以及丰富的功能特性,适用于多种应用场景。
373 1
|
Linux 开发工具 异构计算
【ZYNQ】QSPI Flash 固化程序全攻略
【ZYNQ】QSPI Flash 固化程序全攻略
3288 0
|
SQL 关系型数据库 MySQL
PowerDesigner16.5逆向工程导入
本文介绍了如何通过现有数据库或SQL将数据逆向导入PowerDesigner。首先,需下载并安装PowerDesigner 16.5(32位),并通过指定链接获取软件及教程。接着,安装对应的MySQL ODBC驱动,配置ODBC数据源。最后,在PowerDesigner中通过文件>反向工程>database选项导入数据库。若环境不匹配,可直接导入SQL脚本文件。文中提供了详细步骤与截图指导。
431 0
|
存储 安全 算法
Qt QQueue 详解:从底层原理到高级用法
Qt QQueue 详解:从底层原理到高级用法
566 0