在Qt中使用多线程,目前就我使用过的有两种,一是子类化QThread,重写run函数,在run函数里实现自己的代码,这一部分代码通常是比较耗时,或者干脆直接阻塞的。比如一个while循环,设置一个标志,判断循环结束。
这样写的话,会有一些东西需要了解。
子类化QThread的方法,只有run函数里面的内容是执行在子线程里的,其他的部分,比如槽函数什么的还是在主线程里执行(假设是在主线程开启的该子线程)。
还有一种方法,是子类化QObject,新建一个线程,然后使用MoveToThread把这个类的对象移到新建的线程中,这种做法使得它所有的槽函数都是执行在新开辟的线程里面。
个人推荐使用第二种方法,下面是一个demo
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QTimer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//分配空间,但不指定父对象
myT = new Worker;
//创建子线程
thread = new QThread(this);
//把自定义线程加到子线程中
myT->moveToThread(thread);
connect(this, &Widget::startThreadB, myT, &Worker::mywork);
connect(myT, &Worker::mySignal, this, &Widget::startThreadA);
//当按窗口右上角x时,窗口触发destroyed()
connect(this, &Widget::destroyed, this, &Widget::stopThread);
timer = new QTimer(this);
connect(timer ,&QTimer::timeout, this, &Widget::time);
void Widget::stopThread()
{
//停止线程
thread->quit();
//等待线程处理完手头动作
thread->wait();
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_a_clicked()
{
timer->start(3000);
}
void Widget::startThreadA()
{
//QThread::sleep(3);
qDebug()<<"主线程ID"<<QThread::currentThread();
}
void Widget::time()
{
//启动线程处理函数
thread->start();
emit startThreadB();
}
void Widget::on_pushButton_clicked()
{
timer->stop();
}
worker.cpp
#include "worker.h"
#include <QDebug>
#include <QThread>
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::mywork()
{
emit mySignal();
qDebug()<<"子线程ID"<<QThread::currentThread();
}
}
Worker::~Worker()
{
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "worker.h"
#include <QThread>
namespace Ui {
class Widget;
class QTimer;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void startThreadA();
void stopThread();
private slots:
void on_a_clicked();
void time();
void on_pushButton_clicked();
private:
QTimer *timer;
Ui::Widget *ui;
Worker *myT;
QThread *thread;
signals:
void startThreadB(); //启动子线程的信号
};
#endif // WIDGET_H
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
~Worker();
//线程处理函数
void mywork();
signals:
void mySignal();
public slots:
};
#endif // WORKER_H
需要注意的是
void MyWidget::on_buttonStart_clicked()
{
if(thread->isRunning() == true)
{
return;
}
//启动线程,但是没有启动线程处理函数
thread->start();
myT->setFlag(false);
//不能直接调用线程处理函数,
//直接调用,导致,线程处理函数和主线程是在同一个线程
//myT->myTimeout();
//只能通过 signal - slot 方式调用
emit startThread();
}