參考文章:
https://blog.csdn.net/u012635648/article/details/89504115
1. 異步線程類設計
當線程生命週期結束時通知線程對象銷毀。
只能在堆空間創建線程對象,線程對象不能被外界主動銷毀。
在 run 函數中最後調用 deleteLater () 函數。
線程函數主動申請銷毀線程對象。
使用場合:
線程生命週期不可控,需要長時間運行於後臺的線程。
#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 線程(主線程)。
子線程更新界面狀態的本質是子線程發送信號通知主線程界面更新請求,主線程根據具體信號以及信號參數對界面組件進行修改。
使用信號槽在子線程中更新主界面中進度條的進度顯示信息。
工作線程類:
#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();
}