Qt多线程
Qt创建线程方法一
Qt多线程实现步骤
- 自定义线程类,首先add new,这个类要继承自QThread,但是在Qt5中没有QThread这个选项,所以我们通常继承自QObject类,创建完成之后手动修改,需要包含头文件
#include <QThread>
- 创建子线程对象,在这个项目中以Generate类为例,这是一个生成随机数的子线程类,通过
Generate* gen = new Generate
来实例化对象 - 重写子线程类里面的run方法,run方法通常是protected类型的,在.h文件声明之前最好带上protected,因为最后是通过start方法来调用的,run方法的接口是不对外开放的
- 调用start方法启动子线程
- 线程与线程之间的通信只能通过信号槽函数来建立连接,不能直接通过子线程的数据放到主线程的窗口中显示,期间一定需要信号槽的参与
- 释放线程对象
计算执行用时
声明头文件#include <QElapsedTimer>
,这个类的目的主要是计算在程序运行的过程中某个阶段的执行用时,下面是给出的应用例子,代码示例中的省略号就代表的是循环体或者是函数体
QElapsedTimer time;
time.start();
...
int deltaTime = time.elapsed();
qDebug() << "生成" << m_num << "个随机数总共用时:" << deltaTime << "毫秒";
遇到的问题
QObject::connect: Cannot queue arguments of type ‘QVector’
(Make sure ‘QVector’ is registered using qRegisterMetaType().)
解决方法:在main.cpp中写上qRegisterMetaType<...>("...");
这里面的省略号就是对应的QVector<int>
Qt创建线程方法二
大致步骤
- 创建子线程对象,形如
QThread* t1 = new QThread;
,有多少个子线程,就需要创建多少个QThread - 自定义任务类对象,这个类是继承自QObject而不是QThread,所以里面并不需要重写run方法,只需要自定义一个任务函数即可,比如说working,working函数是可以传入参数的,而重写的run方法是不能有参数的,解决的方法可以通过定义成员变量和信号槽函数传入参数给成员变量
- 将任务对象移动到某个子线程中,形如
gen->moveToThread(t1);
,这行代码的意思是将任务对象移动到t1线程上 - 启动子线程
t1->start()
这里和第一种方法有点区别,虽然启动了子线程,但不会开始工作,需要通过信号槽函数来调用working函数才能让子线程开始工作,任务对象的任务函数可以有多个,亦或者是功能不相同的函数,这也是继承QObject的子线程方法与继承QThread的子线程方法的最大的不同
,继承自QObject方法可以灵活处理子线程的多种功能,而直接继承run方法相对来说比较单一 - 释放线程对象以及任务对象
问题解决
QObject::moveToThread: Current thread (0x9bd1fb0) is not the object’s thread (0xb6e5bf0).
QObject::moveToThread: Cannot move objects with a parent
这个问题分别出现在创建子线程对象和任务对象的时候指定了父对象导致的,它们在实例化对象的时候是一定不要指定父对象的