目錄
一、繼承QThread方式缺點
二、QThread的改進
三、新建立線程方式--信号槽
四、小結
五、完整代碼
一、繼承QThread方式缺點
早期Qt軟體版本隻能提供繼承QThread的方式建立新線程,這是跟面向對象程式設計的早期有關,當時習慣于工程中用繼承的方式去擴充系統的功能,那這樣建立的線程有什麼意義嗎?
1、通過QThread繼承實作的線程是沒有任何意義的;
2、QThread的線程子類僅僅隻有受保護的run()函數接口是不同的,其他接口完全是相同的;
3、QThread對應于作業系統中的線程;
4、QThread用于充當一個線程操作的集合;
5、應該提供更靈活的方式去實作線程入口函數;
6、盡量避免重寫run函數。
二、QThread的改進
1、早期QThread的内部實作
class QThread : public QObject
{
// ...
// ...
protected:
virtual void run() = 0;
// ...
};
2、現代Qt建立新線程的内部實作
class QThread : public QObject
{
Q_OBJECT
// ...
protected:
virtual void run()
{
(void)exec;
}
// ...
};
早期的QThread子類必須重寫run()函數,而現代Qt不在是純虛函數了,類的本身就已經對run()函數進行了預設的實作,啟動了事件循環,這就意味着可以利用信号槽的方式去建立新線程。
三、新建立線程方式--信号槽
現代軟體提倡通過以組合的方式去替代繼承,進而Qt5之後引入新的建立新線程的方式,不再繼續通過繼承QThread的方式,也是Qt提倡使用的,也就是通過信号槽的方式去啟動新的線程,通過moveToThread()的方式去改變目前對象線程的依附性。
1、建立一個業務類繼承于QObject;
//! 1、建立一個業務類繼承于QObject
class NewThreadCreate : public QObject
2、在類中定義一個槽函數Tmain()作為線程的入口函數;
private slots:
//! 2、在類中定義一個槽函數Tmain()作為線程的入口函數
void Tmain();
3、在類中定義一個QThread對象m_thread;
//! 3、在類中定義一個QThread對象m_thread
QThread m_thread;
4、通過moveToThread()改變目前對象線程的依附性至m_thread;
//! 4、通過moveToThread()改變目前對象線程的依附性至m_thread
moveToThread(&m_thread);
5、連接配接新線程m_thread的start()信号到Tmain()槽函數。
//! 5、連接配接新線程m_thread的start()信号到Tmain()槽函數
QObject::connect(&m_thread, &QThread::started, this, &NewThreadCreate::Tmain);
四、小結
1、早期Qt版本隻能通過繼承的方式建立新線程;
2、現代軟體技術提倡以組合的方式代替繼承;
3、QThread應該作為線程操作集合而使用;
4、可以通過信号與槽的方式靈活指定線程的入口函數。
五、完整代碼
1、NewThreadCreate.h
#ifndef NEWTHREADCREATE_H
#define NEWTHREADCREATE_H
#include <QObject>
#include <QThread>
#include <QDebug>
//! 1、建立一個業務類繼承于QObject
class NewThreadCreate : public QObject
{
Q_OBJECT
//! 3、在類中定義一個QThread對象m_thread
QThread m_thread;
public:
NewThreadCreate();
~NewThreadCreate();
void Start();
void Exit(int e);
void Terminate();
private slots:
//! 2、在類中定義一個槽函數Tmain()作為線程的入口函數
void Tmain();
};
#endif // NEWTHREADCREATE_H
2、NewThreadCreate.cpp
#include "NewThreadCreate.h"
NewThreadCreate::NewThreadCreate()
{
//! 4、通過moveToThread()改變目前對象線程的依附性至m_thread
moveToThread(&m_thread);
//! 5、連接配接新線程m_thread的start()信号到Tmain()槽函數
QObject::connect(&m_thread, &QThread::started, this, &NewThreadCreate::Tmain);
}
void NewThreadCreate::Tmain()
{
qDebug() << "NewThreadCreate: " << QThread::currentThreadId();
}
NewThreadCreate::~NewThreadCreate()
{
// 進行線程同步
m_thread.wait();
}
void NewThreadCreate::Start()
{
m_thread.start();
}
void NewThreadCreate::Exit(int e)
{
m_thread.exit(e);
}
void NewThreadCreate::Terminate()
{
m_thread.terminate();
}
3、在主線程中啟動子線程
QThreadMoToThread::QThreadMoToThread(QWidget *parent)
: QWidget(parent)
{
qDebug() << "主線程: " << QThread::currentThreadId();
//! 建立子線程
m_thread = new NewThreadCreate();
m_thread->Start();
}
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9c2MkNXOGNGcoJTWwFjMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzEjNwITNyQTMzATOwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)