QThread笔记

参考文章：
https://blog.csdn.net/u012635648/article/details/89504115
1. 异步线程类设计

线程生命期结束时通知线程对象销毁。
只能在堆空间创建线程对象，线程对象不能被外界主动销毁。
在 run 函数中最后调用 deleteLater () 函数。
线程函数主动申请销毁线程对象。
使用场合：
线程生命期不可控，需要长时间运行于后台的线程。

Copy
#ifndef ASYNCTHREAD_H
#define ASYNCTHREAD_H

#include <QThread>

class AsyncThread : public QThread
{
Q_OBJECT
protected:
void run()
{

deleteLater();
}
explicit AsyncThread(QObject* parent = 0):QThread(parent)
{

}
~AsyncThread()
{

}
public:
static AsyncThread* newThread(QObject* parent = 0)
{
return new AsyncThread(parent);
}
};

#endif // ASYNCTHREAD_H

2. 子类化 QThread

QThread 的两种使用方法:
（1）不使用事件循环
A、子类化 QThread
B、重写 run 函数，run 函数内有一个 while 或 for 的死循环
C、设置一个标记为来控制死循环的退出。
适用于后台执行长时间的耗时操作，如文件复制、网络数据读取。
（2）使用事件循环。
A、子类化 QThread
B、重写 run 使其调用 QThread::exec () ，开启线程的事件循环
C、为子类定义信号和槽，由于槽函数并不会在新开的 Thread 运行，在构造函数中调用 moveToThread (this)。
适用于事务性操作，如文件读写、数据库读写。

3. 信号槽方式

使用信号槽解决多线程与界面组件的通信的方案：
A、在子线程中定义界面组件的更新信号
B、在主窗口类中定义更新界面组件的槽函数
C、使用异步方式连接更新信号到槽函数
子线程通过发送信号的方式更新界面组件，所有的界面组件对象只能依附于 GUI 线程（主线程）。
子线程更新界面状态的本质是子线程发送信号通知主线程界面更新请求，主线程根据具体信号以及信号参数对界面组件进行修改。
使用信号槽在子线程中更新主界面中进度条的进度显示信息。
工作线程类：

Copy
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>

class WorkThread : public QThread
{
Q_OBJECT
signals:
void signalProgressValue(int value);
protected:
void run()
{
work();
exec();
}
public:
WorkThread()
{
m_stop = false;
moveToThread(this);
}
void work()
{
for(int i = 0; i < 11; i++)
{
emit signalProgressValue(i*10);
sleep(1);
}
}
};

#endif // WORKTHREAD_H

主界面类：
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QProgressBar>
#include "WorkThread.h"

class Widget : public QWidget
{
Q_OBJECT
QProgressBar* m_progress;//进度条
WorkThread* m_thread;//工作线程
public:
Widget(QWidget *parent = 0):QWidget(parent)
{
m_progress = new QProgressBar(this);
m_progress->move(10, 10);
m_progress->setMinimum(0);
m_progress->setMaximum(100);
m_progress->setTextVisible(true);
m_progress->resize(100, 30);
m_thread = new WorkThread();
m_thread->start();
connect(m_thread, SIGNAL(finished()), m_thread, SLOT(deleteLater()));
//连接工作线程的信号到界面的槽函数
connect(m_thread, SIGNAL(signalProgressValue(int)), this, SLOT(onProgress(int)));
}
~Widget()
{
}
protected slots:
void onProgress(int value)
{
m_progress->setValue(value);
}
};
#endif // WIDGET_H

Main函数：
#include "Widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();

return a.exec();
}