多线程的使用主要是为了处理比较耗时的过程。这可以用以下图来形象地描述:
目前,由于继承QObject的多线程实现方法更加灵活,Qt官方推荐使用该方法实现多线程。
想用图来描述实现的过程,发现也不好表达,将就着看吧:
1、创键一个继承于 QObject 的自定义线程类(如:MyThread),用来盛放比较耗时,需要放入子线程的处理函数
2、 在主线程(亦称界面线程)中创建一个子线程(QThread* subthread = new QThread(this))
3、新建一个自定义线程类对象(MyThread* m_MyThread = new MyThread())
4、将自定义线程类对象移入子线程容器中(m_MyThread->moveToThread(subthread)),其实也可以移入多个自定义线程类到同一个subthread中,这时他们就共享一个子线程了
5、连接主线程和子线程之间的信号和槽
connect ( this, &MainWindow::StartThread, m_MyThread, &MyThread::MyWork )
connect (m_MyThread, &MyThread::signal_back, this, &MainWindow::slot_handle_finish )
6、子线程使用完毕需要回收销毁,不然该线程会一直占用,而系统可分配的线程数量是有限的
subthread->qiut(); //该停止函数比较弱,会等到线程处理函数MyWork()的任务执行完之后,才会停止线程
subthread->wait();
所有通常会加入一个标志位,来终止任务。
以上过程就实现了,从主线程进入子线程处理耗时问题,到处理完成后返回主线程的过程。
接下来看代码,有点长。。。
mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include
class MyThread : public QObject
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void MyWork(); //线程处理函数定义
void setFlag(bool flag = true);
signals:
void signal_back();//处理结果返回信号
private:
bool isStop;
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
#include
#include
MyThread::MyThread(QObject *parent) : QObject(parent)
{
isStop = false;
}
void MyThread::MyWork() //线程处理函数:具体处理的事情
{
while(!isStop)
{
QThread::sleep(1);
emit signal_back(); //发送返回信号
qDebug() << "the child thread number:" << QThread::currentThread();
}
}
void MyThread::setFlag(bool flag)
{
isStop = flag;
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include
#include "mythread.h"
#include
namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
Q_OBJECT
public:
explicit MyWidget(QWidget *parent = 0);
~MyWidget();
void slot_handle_finish();
signals:
void StartThread();
private slots:
void on_BtnStart_clicked();
void on_BtnStop_clicked();
private:
Ui::MyWidget *ui;
MyThread * m_MyThread;
QThread * subthread;
void CloseWidget();
};
#endif // MYWIDGET_H
mywidget.cpp
#include "mywidget.h"
#include "ui_mywidget.h"
#include
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyWidget)
{
ui->setupUi(this);
//creat a child thread
subthread = new QThread(this);
//creat a new object m_MyThread
m_MyThread = new MyThread();
//move the new object to child thread
m_MyThread->moveToThread(subthread);
connect(this, &MyWidget::StartThread, m_MyThread, &MyThread::MyWork);
connect(m_MyThread, &MyThread::signal_back, this, &MyWidget::slot_handle_finish);
qDebug() << "the main thread number:" << QThread::currentThread();
connect(this, &MyWidget::destoryed, this, &MyWidget::CloseWidget); //左上角窗口关闭
}
MyWidget::~MyWidget()
{
delete ui;
}
void MyWidget::on_BtnStart_clicked()
{
if(subthread->isRunning() == true) return;
m_MyThread->setFlag(false);
//start the child thread
subthread->start();
//启动了线程,但是并没有进入线程
//必须通过信号/槽的方式进入子线程
//直接通过m_MyThread->Mywork()是不行的,这样MyWork()中的线程就是主线程
emit StartThread();
}
void MyWidget::slot_handle_finish()
{
static int i = 0;
i++;
ui->lcdNumber->display(i);
}
void MyWidget::on_BtnStop_clicked()
{
if(subthread->isRunning() == true) return;
m_MyThread->setFlag();
subthread->quit();
subthread->wait();
}
void MyWidget::CloseWidget()
{
m_MyThread->setFlag();
subthread->quit();
subthread->wait();
delete m_MyThread;
}
以上过程就启动线程,即通过开始按钮,开始计时
注:
1、子线程的处理函数中不能操作图形界面,只能进行数据处理,因为是后台运行
2、connect函数的第5个参数ConnectionType的问题