Qt多线程

Qt中使用多线程常用的方式有2种

1. 继承QThread重写run函数

线程在执行过程中是不能释放线程对象的可以使用

QThread *thread = new QThread(this);
connect(thread, SIGNAL(finished()),thread ,SLOT(deleteLater()));

注意这2句代码是在主线程中执行的线程对象属于主线程,deleteLater由主线程执行,如果在子线程中创建线程对象属于子线程要考虑子线程是否还能触发信号执行槽函数

有父对象的话,父对象释放时,会来释放该子对象

 

class CThread : public QThread
{
public:
    CThread(QObject* parent = nullptr);

    ~CThread();

    //线程执行完毕后,运行该函数 与QThread::finished信号连接
    void threadFinish();

protected:

    //重写run函数 子线程会执行该函数类的代码
    void run();

};


CThread::CThread(QObject* parent) : QThread(parent)
{
    qDebug() << "cthread cthread";

    //执行完毕后执行ThreadFinish
    connect(this, &CThread::finished, this, &CThread::threadFinish);
}

CThread::~CThread()
{
    qDebug() << "cthread ~cthread";
}

//我们这里重写了run函数且没有调用 QThread::exec() 函数(消息循环)子线程收到信号执行槽函数依赖消息循环   所以该线程不能收到信号执行槽函数
//打印内容后就会触发finished信号 表示线程执行完毕
void CThread::run()
{
    qDebug() << "cthread run threadId: " << QThread::currentThreadId();
}

void CThread::threadFinish()
{
    qDebug() << "cthread finish";
}


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CMainWindow w;
    w.show();

    CThread* pThread = new CThread();
    
    //connect只是一个静态方法
    //线程执行完毕后释放pThread对象
    QObject::connect(pThread, &CThread::finished, pThread, &CThread::deleteLater);
    //启动线程
    pThread->start();
    
    return a.exec();
}

输出:

main thread id: 0x1dd8

cthread cthread

cthread run threadId: 0x24e0

cthread finish

cthread ~cthread

 

2. moveToThread

这种方式依赖,子线程的QThread::exec() 子程序的消息循环中收到信号,执行对应的槽函数

消息循环在程序结束时如果没退出,qt会帮你退出

注意:pMyWork->moveToThread(pThread);   pMyWork不能有父对象

class CMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit CMainWindow(QWidget *parent = nullptr);
    ~CMainWindow();

private:
    Ui::CMainWindow *ui;

signals:
    void doMyWork();
};


CMainWindow::CMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::CMainWindow)
{
    ui->setupUi(this);

    qDebug() << "main thread id: " << QThread::currentThreadId();

    QThread* pThread = new QThread();   
    //QThread 的run函数里面会执行(void) exec();  夸线程响应槽函数依赖消息循环 消息循环一般不知道子线程什么时候会执行完毕  可以使用这种方式释放线程对象
    //注意这里是主线程 主线程调用deleteLater()一般没有问题, 如果线程对象属于子线程要注意子线程是否还能响应该信号
    connect(pThread, &QThread::finished, pThread, &QThread::deleteLater);

    CMyWork* pMyWork = new CMyWork();
    //注意这里 pMyWork不能有父对象
    pMyWork->moveToThread(pThread);

    //触发信号后,在子线程中执行TestWork 依赖QThread::exec()  收到信号后执行
    connect(this, &CMainWindow::doMyWork, pMyWork, &CMyWork::TestWork);

    pThread->start();

    //触发信号
    emit doMyWork();
}

CMainWindow::~CMainWindow()
{
    delete ui;
}

class CMyWork : public QObject
{
    Q_OBJECT
public:
    explicit CMyWork(QObject *parent = nullptr);

    void TestWork();

signals:

public slots:
};

CMyWork::CMyWork(QObject *parent) : QObject(parent)
{

}

void CMyWork::TestWork()
{
    qDebug() << "myThread testWork ThreadId" << QThread::currentThreadId();
}

输出:

main thread id: 0x43a0

myThread testWork ThreadId 0x43c0

 

QtConcurrent

QtConcurrent 是命名空间 (namespace),它提供了高层次的函数接口 (APIs),使所写程序,可根据计算机的 CPU 核数,自动调整运行的线程数目。

函数原型

QFuture<T> QtConcurrent::run(QThreadPool::globalInstance(), function, ...) ;
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...);

使用准备
使用QtConcurrent需要在.pro文件增加 QT += concurrent
如果是使用VS+Qt,则需要增加模块Concurrent
 

#include "CMainWindow.h"
#include <QDebug>
#include <QFuture>
#include <QThread>
#include <QtConcurrent>
#include <QThreadPool>

CMainWindow::CMainWindow(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	connect(ui.pushButton, &QPushButton::clicked, this, &CMainWindow::onButtonClick);
}

void test(QString name)
{
	qDebug() << name << "from" << QThread::currentThreadId();
}

void CMainWindow::onButtonClick()
{
	qDebug() << "main thread" << QThread::currentThreadId();


	//不给定线程池    使用QThreadPool::globalInstance()

	QFuture<void> fun1 = QtConcurrent::run(test, QString("yuan"));
	//等待线程执行结束
	fun1.waitForFinished();

	QFuture<void> fun2 = QtConcurrent::run([]() 
	{
		qDebug() << "lambda" << QThread::currentThreadId();
	});

	//自定义线程池
	QThreadPool threadPool;
	QFuture<void> fun3 = QtConcurrent::run(&threadPool, []()
	{
		qDebug() << "threadPool" << QThread::currentThreadId();
	});
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值