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 继承

目录
相关文章
|
8月前
【Qt】- QMainWindwo
【Qt】- QMainWindwo
|
8月前
|
Linux 定位技术 C++
【Qt】-学Qt前的准备
【Qt】-学Qt前的准备
|
开发框架 Linux API
2023-6-1-Qt是什么
2023-6-1-Qt是什么
121 0
Qt之QImageReader
简述 QImageReader类为从文件或设备读取图像提供了一个独立的接口。 读取图像最常用的方法是通过构造QImage和QPixmap,或通过调用QImage::load()和QPixmap::load()。QImageReader是一个专业读取图像的类,可以有更多的控制,例如,可以通过调用setScaledSize()读取图像成特定的大小,通过调用setClipRec
2631 0
|
Linux Android开发 C++
Qt资料大全
简述 发福利了、发福利了、发福利了,重要的事情说三遍。。。 为了方便更多Qter了解、学习Qt,现将相关资源进行整理,主要内容包括:Qt官网、编码风格、GitHub & Third-Party、社区论坛、博客、书籍等。 满满的都是干货,独乐乐不如众乐乐。。。 简述 Qt官网 编码风格 GitHub Third-Party 社区论坛 博客 书籍 更多
2928 0
|
Java C++
Qt之QFuture
简述 QFuture 类代表一个异步计算的结果。 要启动一个计算,使用 Qt之Concurrent框架 中的 APIs 之一。 QFuture 允许线程与一个或多个结果同步,这些结果将在稍后的时间点准备就绪,该结果可以是具有默认构造函数和拷贝构造函数的任何类型。如果一个结果在调用 result()、resultAt() 或 results() 函数时不可用,QFutur
2056 0
|
存储
Qt之QUrlQuery
简述 QUrlQuery 类提供了一种方法来操纵 URL 查询中的 key-value 对。 简述 详细描述 编码 处理空格和加号 全解码 非标准分隔符 使用 QUrlQuery 分隔符 查询 删除 是否为空 详细描述 QUrlQuery 用来解析 URL 中的查询字符串,像下面这样: 上述的查询字符串在 URL 中 被用来传输
2893 0
Qt之QScrollArea
简述 QScrollArea提供了一个滚动视图到另一个部件。 滚动区域用于显示一个画面中的子部件的内容。如果部件超过画面的大小,视图可以提供滚动条,这样就都可以看到部件的整个区域。 简述 基本使用 对齐方式 调整部件大小 手动调整 自动调整 获取与移除部件 获取 移除 基本使用 子部件必须使用setWidget()指定,例如: QLab
3264 0

热门文章

最新文章