赞
踩
在最初学习Qt的多线程时,我们往往接触到的是创建一个继承于 QThread 的类,重写run()函数,并使用start()方法间接调用 run() 函数启动线程;从Qt 4.4开始,Qt官方推出了新的线程使用方式,并推荐使用该方式;
直接继承QThread并重写run函数的方式较为方便简洁,缺点是只有run函数运行在子线程,适合单一的任务;
moveToThread的方式必须通过信号槽机制调用函数,相对于继承QThread而言较为复杂,但是所有的函数都运行在子线程中,如何选择还需根据实际需求。
下面对moveToThread的使用进行简单的演示:
1.首先创建一个Qt工程,并添加线程类
右键工程,添加一个继承于 QObject 的类(我这里叫 MoveThread),并在主线程的头文件中添加QThread 和 新类的头文件;
#include <QThread>
#include "movethread.h"
2.MoveThread 类中添加槽函数
#ifndef MOVETHREAD_H #define MOVETHREAD_H #include <QObject> class MoveThread : public QObject { Q_OBJECT public: explicit MoveThread(QObject *parent = nullptr); public slots: void functionOne(); void functionTwo(); signals: }; #endif // MOVETHREAD_H
简单实现,打印当前线程id
#include "movethread.h" #include <QDebug> #include <QThread> MoveThread::MoveThread(QObject *parent) : QObject(parent) { } void MoveThread::functionOne() { qDebug() << "子线程id:" << QThread::currentThread(); } void MoveThread::functionTwo() { qDebug() << "子线程id:" << QThread::currentThread(); }
3.主线程类中添加成员MoveThread与 QThread 成员(我这里使用指针)
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QThread> #include "movethread.h" QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; QThread *thread; MoveThread *moveThread; }; #endif // WIDGET_H
4.打开设计师界面,添加两个button,用于触发两个槽函数
5.在主窗口的构造函数中为MoveThread 和QThread 成员申请空间,调用moveToThread,直接启动线程,并打印主线程号,上一步骤中添加的两个按钮分别绑定 MoveThread 中的两个槽函数
#include "widget.h" #include "ui_widget.h" #include <QDebug> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); thread = new QThread(this); moveThread = new MoveThread(); moveThread->moveToThread(thread); thread->start(); qDebug() << "主线程id:" << QThread::currentThread(); connect(ui->btnFun1, &QPushButton::clicked, moveThread, &MoveThread::functionOne); connect(ui->btnFun2, &QPushButton::clicked, moveThread, &MoveThread::functionTwo); }
注意,此处 thread 指定了父对象,moveThread 不能指定父对象,否则会导致线程方法仍在主线程;
由于MoveThread没有指定父对象,所以不要忘记手动管理内存,在主线程的析构函数中处理
Widget::~Widget()
{
delete ui;
if(thread->isRunning())
{
thread->quit();
thread->wait();
}
if(moveThread)
{
delete moveThread;
moveThread = nullptr;
}
}
6.运行,分别点击两个按钮,输出如下
可以看到, 两个槽函数都运行在子线程。
附完整demo:ThreadDemo
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。