这个是本文章实例的源码地址:https://gitee.com/CogenCG/QThreadExample.git
子类化QThread来实现多线程, QThread只有run函数是在新线程里的,其他所有函数都在QThread生成的线程里。正确启动线程的方法是调用QThread::start()来启动,如果直接调用run成员函数,这个时候并不会有新的线程产生( 原因: 可以查看往期《QThread源码浅析》文章,了解下run函数是怎么被调用的)。
一、步骤
- 子类化 QThread;
- 重写run,将耗时的事件放到此函数执行;
- 根据是否需要事件循环,若需要就在run函数中调用 QThread::exec() ,开启线程的事件循环。事件循环的作用可以查看往期《QThread源码浅析》文章中《QThread::run()源码》小节进行阅读;
- 为子类定义信号和槽,由于槽函数并不会在新开的线程运行,所以需要在构造函数中调用 moveToThread(this)。 注意:虽然调用moveToThread(this)可以改变对象的线程依附性关系,但是QThread的大多数成员方法是线程的控制接口,QThread类的设计本意是将线程的控制接口供给旧线程(创建QThread对象的线程)使用。所以不要使用moveToThread()将该接口移动到新创建的线程中,调用moveToThread(this)被视为不好的实现。
接下来会通过 使用线程来实现计时器,并实时在UI上显示 的实例来说明不使用事件循环和使用事件循环的情况。(此实例使用QTimer会更方便,此处为了说明QThread的使用,故使用线程来实现)
二、不使用事件循环实例
InheritQThread.hpp
class InheritQThread:public QThread
{
Q_OBJECT
public:
InheritQThread(QObject *parent = Q_NULLPTR):QThread(parent){
}
void StopThread(){
QMutexLocker lock(&m_lock);
m_flag = false;
}
protected:
//线程执行函数
void run(){
qDebug()<<"child thread = "<<QThread::currentThreadId();
int i=0;
m_flag = true;
while(1)
{
++i;
emit ValueChanged(i); //发送信号不需要事件循环机制
QThread::sleep(1);
{
QMutexLocker lock(&m_lock);
if( !m_flag )
break;
}
}
}
signals:
void ValueChanged(int i);
public:
bool m_flag;
QMutex m_lock;
};
mainwindow.hpp
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr) :
QMainWindow(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
qDebug()<<"GUI thread = "<<QThread::currentThreadId();
WorkerTh = new InheritQThread(this);
connect(WorkerTh, &InheritQThread::ValueChanged, this, &MainWindow::setValue);
}
~MainWindow(){
delete ui;
}
public slots:
void setValue(int i){
ui->lcdNumber->display(i);
}
private slots:

本文通过实例讲解了QThread的使用方法,包括子类化QThread、使用事件循环、正确退出线程及释放资源等内容。
最低0.47元/天 解锁文章
1884

被折叠的 条评论
为什么被折叠?



