Qt中开启多线程有两种方式,一种是重构run函数,另一种是moveToThread的方式,这里我主要介绍一下moveToThread,这是Qt4.8后新增的功能,也是Qt开发者极力推荐使用的多线程方式。
首先需要为子线程单独创建一个类,继承QObject。
如上图,让耗时函数在worker类中执行。
之后在主线程引用此类的头文件和QThread,并实例化耗时类对象和线程对象。
#include <QThread>
#include "worker.h"
QThread my_thread;
Worker *my_worker= new Worker;//实例化耗时类
my_worker->moveToThread(&my_thread);//开辟子线程,将耗时类放入子线程中去
接下来是连接信号与槽:
信号与槽函数自行在对应头文件中定义。
connect(&my_thread,&QThread::finished,my_worker,&QObject::deleteLater);//线程析构
connect(this,&Widget::sig_start,my_worker,&Worker::slot_start);//启动线程
连接好信号与槽后,就可以正式开启子线程了:
my_thread.start();//调用线程
emit this->sig_start();//启动线程信号
因为子线程的开启和析构会占用大量资源,所以一般来说子线程会以循环的方式持续执行,那么循环的退出就至关重要了,不然当关闭程序时要么出现程序假死或者程序关闭但是线程还在持续执行的现象。
我的方法是给子线程的循环设置入口标志位及出口标志位:
#include "worker.h"
volatile bool start=1;//线程标志位
void Worker::slot_start()
{
for(;;)
{
if(start==1)//标志位=1,循环执行耗时函数
{
......//耗时函数
}
else//标志位=0,跳出循环,线程执行结束
{
break;
}
}
}
当析构时,设置线程标志位=0,等待线程完成当前循环,并退出线程。
my_worker->start=0;//子线程标志位=0,线程跳出循环
my_thread.quit();
my_thread.wait();//退出线程,并等待线程完成当前循环