天天看點

Qt多線程建立之moveToThread一、繼承QThread方式缺點二、QThread的改進三、新建立線程方式--信号槽四、小結五、完整代碼

目錄

一、繼承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();
}
           
Qt多線程建立之moveToThread一、繼承QThread方式缺點二、QThread的改進三、建立立線程方式--信号槽四、小結五、完整代碼