Qt学习:子线程QThread的使用

在开发过程中,碰到一些耗时的操作,如果直接在主线程里处理,UI将会出现假死的现象,甚至程序会崩溃,所以这类操作最好放在子线程当中。

这里有2个对象,一个是QThread,即子线程;另一个是继承于QObject的一个类,这个是要在子线程里运行的代码片段。

因为这个QObject非常基础,所以几乎所有继承于其他组件的自定义类,都间接地继承于QObject,都可以放入QThread中运行。

1、首先定义一个要在子线程跑的自定义类

ThreadObject.h:

#ifndef THREADOBJECT_H
#define THREADOBJECT_H
#include <QPrinter>
#include <QPainter>
#include <mytablewidget.h>
#include <QObject>

class ThreadObject : public QObject
{
    Q_OBJECT
public:
    explicit ThreadObject(QObject *parent = 0);
    ~ThreadObject();

signals:
    void onRunCompletedSignal();

public slots:
    void runOutputPdf(QString path,MyTableWidget * table,QString currentProgressName,QString currentProgressVer);
};

#endif // THREADOBJECT_H

ThreadObject.cpp:

#include "threadobject.h"

ThreadObject::ThreadObject(QObject *parent) : QObject(parent)
{
}
void ThreadObject::runOutputPdf(QString path,MyTableWidget * table,QString currentProgressName,QString currentProgressVer)
{
    // 一些耗时的操作.
    emit onRunCompletedSignal();
}
ThreadObject::~ThreadObject()
{

}

这个类没有很特别,只有两点需要注意:

1、在执行耗时操作完毕之后,要发送一个信号,这个信号将会在主线程被接收到;

2、定义一个public slot,这个回调将会有主线程的信号(signal)来触发,运行。


2、在主线程里调用

    if(thread)
        return;

    // 实例化子线程
    thread = new QThread;
    // 实例化子线程对象
    threadObject = new ThreadObject;
    // 将子线程对象移到子线程
    threadObject->moveToThread(thread);
    // 线程finished->线程自己deleteLater
    connect(thread,&QThread::finished,thread,&QThread::deleteLater);
    // 线程finished->线程对象deleteLater
    connect(thread,&QThread::finished,threadObject,&ThreadObject::deleteLater);
    // 主线程发送信号->线程对象启动run函数
    connect(this,&ExtractProgressEditPage::startThreadObjectRunOutputPdfSignal,threadObject,&ThreadObject::runOutputPdf);
    // 接收线程实体运行结束发送的信号,在回调里quit,quit之后会接收到finished,然后再根据finished消息进一步操作
    connect(threadObject,&ThreadObject::onRunCompletedSignal,this,&ExtractProgressEditPage::onOutputPdfCompleted);

    thread->start();

    emit startThreadObjectRunOutputPdfSignal(path,table,currentProgressName,currentProgressVer);

3、子线程的销毁:注意,必须手动对子线程进行quit,并不是代码运行完了他就自动销毁!

如上所述,在耗时操作运行完毕之后,即我们可以结束线程之时,发射一个信号,这个信号在主线程被捕获,然后在回调里我们要对这个子线程进行注销:

void ExtractProgressEditPage::onOutputPdfCompleted()
{
    qDebug()<<"pdf output completed!";
    thread->quit();
    thread->wait();
    thread->deleteLater();
    thread = NULL;// 加了这个是为了以上代码有的地方通过if(thread)来判断线程是否已运行结束,然后是否可以进行新的一个运行
}

在调用了quit之后,他自然会触发finished,然后触发其他我们如上面信号槽所定义的其他行为,比如对ThreadObject进行deleteLater。






猜你喜欢

转载自blog.csdn.net/wzj0808/article/details/80517012