繼承於QObject 的多線程實現

      QT中的多線程操作有兩種方法可以實現,一種是直接使用官方的QThread,通過重寫QThread::run()方法實現線程處理;另外一種則是通過繼承QObject類的對象,將其實現函數movetoThread()實現。

 

QThread類中的幾個官方函數和信號的作用

       QThread::exec() —— 使線程進入事件循環狀態,並處於wait()狀態,直到調用exit()或quit()退出,一般在run()中調用

       QThread::exit()  —— 告知線程從事件循環中退出,並返回returnCode的值

       QThread::run() —— 線程的運行起點,在調用Start()後調用,從該函數返回將結束線程

       QThread::quit() —— 告知線程的事件循環退出並返回0,如果沒有事件循環,這個函數則什麼也不做

       QThread::start() —— 調用該函數啓動線程,操作系統會根據優先級來調度

       QThread::terminate() —— 終止當前線程,但不發出finish信號,且線程結束後自己不能去做清理工作,較危險

 

       QThread::finished —— finish信號,在線程執行完畢前發出該信號,quit()和wait()調用後線程結束則發出該信號

       

兩種實現方法有什麼不同?

1、通過QThread::run實現的多線程操作,僅僅run()方法處於新的線程中,而對象的其他非run()函數則仍處於舊線程(即創建QThread對象的線程)中;而繼承於QObject類的實現中,整個新建的線程類都處於新的線程中

2、通過QThread::run實現的多線程如果要支持事件循環,需要在run()中調用QThread::exec(),否則不能正常發送信號;而繼承於QObject的多線程則可以正常使用信號/槽函數機制實現事件循環

 

繼承QObject的多線程實現

1、創建一個MyThread類,繼承於QObject,將需要做的耗時處理放到函數MyWork()中

2、在MyThread類中創建一個volatile修飾的私有變量isStop用於控制線程的結束,並聲明一個函數用於修改它的值

3、在主窗體Widget的構造函數中分別創建一個MyThread對象m_MyThread和一個QThread對象subthread,通過m_MyThread->moveToThread(subthread)將MyThread對象移至新的子線程中

4、連接主窗體的開始線程信號和m_MyThread的Mywork處理函數;連接子線程的finish()信號和m_MyThread的QObject::deletelater函數

 

需要注意的關鍵點

1、繼承QObject類的多線程實現中,調用subthread->start()時僅僅是啓動了線程但並沒有進入線程,需要發送開始線程信號才能進入子線程

void Widget::on_Start_Btn_clicked()
{
    if(subthread->isRunning())
    {
        subthread->wait();
        return;
    }
    m_MyThread->setFlag(false);
    qDebug() << "set flag = false !";
    subthread->start();
    //啓動了線程但並沒有進入線程,需要通過信號/槽的方式進入子線程
    //直接調用m_MyThread->MyWork()是錯誤的,這樣Mywork是在主線程中處理
    emit StartThread();
    qDebug() << "發射開始線程信號";
}

 2、線程的正確退出步驟應該是:先設置isStop變量。使得線程結束Mywork()中的循環;再調用quit()結束事件循環;最後調用wait()釋放線程槽函數資源退出線程。在這一過程中會發送finish信號,之後會自動調用deletelater刪除線程對象

void Widget::on_close_Btn_clicked()
{
    if(subthread->isRunning())
    {
        qDebug() << "close click!";
        m_MyThread->setFlag(true);
        qDebug() << "set flag = TRUE";
        subthread->quit();
        qDebug() << "quit";
        subthread->wait();
//        if(subthread->isFinished())
//        delete subthread;
    }
}

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章