欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Qt線程QThread開(kāi)啟和安全退出的實(shí)現(xiàn)

 更新時(shí)間:2023年06月07日 09:46:10   作者:Qt開(kāi)發(fā)老杰  
本文主要介紹了Qt線程QThread開(kāi)啟和安全退出的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1、線程開(kāi)啟

Qt中,開(kāi)啟子線程,一般有兩種方法:

a, 定義工作類worker:

worker繼承 QThread, 重寫(xiě)run函數(shù),在主線程中實(shí)例化worker,把耗時(shí)工作放進(jìn)worker的run函數(shù)中完成,結(jié)束后,往主線程中發(fā)信號(hào),傳遞參數(shù)即可。

注意:此worker的實(shí)例,只有run函數(shù)在子線程中執(zhí)行,worker的其他函數(shù),均在主線程中執(zhí)行。

如果子線程已經(jīng)start開(kāi)啟,run函數(shù)尚未運(yùn)行完時(shí),再次start,此時(shí)子線程不會(huì)有任何操作,run函數(shù)不會(huì)被重新調(diào)用,會(huì)繼續(xù)執(zhí)行run函數(shù)。

b, 定義工作類worker:

worker繼承Qobject,在worker中完成耗時(shí)操作,并在主線程中 #include “worker.h”進(jìn)來(lái),隨后,在主線程中New出幾個(gè)子線程QThread,使用moveToThread()函數(shù),把worker轉(zhuǎn)移進(jìn)入子線程,例如:

pWorker = new Worker;
pThread1 = new QThread;
pWorker->moveToThread(pThread1)

之后,再根據(jù)需求,看何時(shí)開(kāi)啟子線程:pThread1->start();
如果線程已經(jīng)運(yùn)行,你重復(fù)調(diào)用start其實(shí)是不會(huì)進(jìn)行任何處理。

2、線程關(guān)閉

對(duì)于上面a類,在run中開(kāi)啟的子線程,如果run中沒(méi)有調(diào)用exec(),使用quit(),exit(),是無(wú)法跳出run中的循環(huán),終止子線程的。不會(huì)發(fā)生任何效果,QThread不會(huì)因?yàn)槟阏{(diào)用quit()函數(shù)而退出正在運(yùn)行到一半的run。
但使用QThread的terminate()方法,可以立刻結(jié)束子線程,但這個(gè)函數(shù)存在非常不安定因素,不推薦使用。那么如何安全的終止一個(gè)線程呢?

最簡(jiǎn)單的方法是添加一個(gè)bool變量,通過(guò)主線程修改這個(gè)bool變量來(lái)進(jìn)行終止,但這樣有可能引起訪問(wèn)沖突,需要對(duì)其進(jìn)行加鎖。

void myThread::run()
{
    int count = 0;
    m_isCanRun = true;//標(biāo)記可以運(yùn)行
    QString str = QString("%1->%2,thread id:%3").arg(__FILE__).arg(__FUNCTION__)
    .arg((unsigned int)QThread::currentThreadId());
    emit message(str);
    while(1)
    {
        sleep(1);
        ++count;    
        doSomething();
        if(m_runCount == count)
        {
            break;
        }
        {
            QMutexLocker locker(&m_lock);// 此處加鎖,防止訪問(wèn)沖突
            if(!m_isCanRun)//在每次循環(huán)判斷是否可以運(yùn)行,如果不行就退出循環(huán)
            {
                return;
            }
        }
    }
}

因此在子線程的run函數(shù)的循環(huán)中遇到m_isCanRun的判斷后就會(huì)退出run函數(shù),繼承QThread的函數(shù)在運(yùn)行完run函數(shù)后就視為線程完成,會(huì)發(fā)射finish信號(hào)。

子線程指針,盡量不要去delete ,這樣不安全。一般會(huì)綁定QObject::deleteLater()方法。

connect(pThread,&QThread::finished ,thread,&QObject::deleteLater);

線程結(jié)束后調(diào)用deleteLater來(lái)銷(xiāo)毀分配的內(nèi)存。

對(duì)于上面b類,在Qt4.8之后,Qt多線程的寫(xiě)法最好還是通過(guò)QObject來(lái)實(shí)現(xiàn),和線程的交互通過(guò)信號(hào)和槽(實(shí)際上其實(shí)是通過(guò)事件)聯(lián)系。

繼承QObject多線程的方法線程的創(chuàng)建很簡(jiǎn)單,只要讓QThread的start函數(shù)運(yùn)行起來(lái)就行,但是需要注意銷(xiāo)毀線程的方法: 在線程創(chuàng)建之后,這個(gè)QObject的銷(xiāo)毀不應(yīng)該在主線程里進(jìn)行,而是通過(guò)deleteLater槽進(jìn)行安全的銷(xiāo)毀,因此,繼承QObject多線程的方法在創(chuàng)建時(shí)有幾個(gè)槽函數(shù)需要特別關(guān)注:

  • 一個(gè)是QThread的finished信號(hào)對(duì)接QObject的deleteLater使得線程結(jié)束后,繼承QObject的那個(gè)多線程類會(huì)自己銷(xiāo)毀
  • 另一個(gè)是QThread的finished信號(hào)對(duì)接QThread自己的deleteLater,這個(gè)不是必須,下面官方例子就沒(méi)這樣做:
class Worker : public QObject
{
    Q_OBJECT
    public slots:
    void doWork(const QString &parameter) {
    QString result;
    /* ... here is the expensive or blocking operation ... */
    emit resultReady(result);
    }
signals:
    void resultReady(const QString &result);
};
class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
    Worker *worker = new Worker;
    worker->moveToThread(&workerThread);
    connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
    connect(this, &Controller::operate, worker, &Worker::doWork);
    connect(worker, &Worker::resultReady, this, &Controller::handleResults);
    workerThread.start();
    }
    ~Controller() {
    workerThread.quit();
    workerThread.wait();
    }
public slots:
    void handleResults(const QString &);
signals:
    void operate(const QString &);
};

使用QObject創(chuàng)建多線程的方法如下:

  • 寫(xiě)一個(gè)繼承QObject的類,對(duì)需要進(jìn)行復(fù)雜耗時(shí)邏輯的入口函數(shù)聲明為槽函數(shù)
  • 此類在舊線程new出來(lái),不能給它設(shè)置任何父對(duì)象
  • 同時(shí)聲明一個(gè)QThread對(duì)象,在官方例子里,QThread并沒(méi)有new出來(lái),這樣在析構(gòu)時(shí)就需要調(diào)用- – QThread::wait(),如果是堆分配的話, 可以通過(guò)deleteLater來(lái)讓線程自殺
  • 把obj通過(guò)moveToThread方法轉(zhuǎn)移到新線程中,此時(shí)object已經(jīng)是在線程中了
  • 把線程的finished信號(hào)和object的deleteLater槽連接,這個(gè)信號(hào)槽必須連接,否則會(huì)內(nèi)存泄漏
  • 正常連接其他信號(hào)和槽(在連接信號(hào)槽之前調(diào)用moveToThread,不需要處理connect的第五個(gè)參數(shù),否則就顯示聲明用Qt::QueuedConnection來(lái)連接)
  • 初始化完后調(diào)用’QThread::start()’來(lái)啟動(dòng)線程
  • 在邏輯結(jié)束后,調(diào)用QThread::quit退出線程的事件循環(huán)

 到此這篇關(guān)于Qt線程QThread開(kāi)啟和安全退出的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Qt QThread開(kāi)啟和退出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++操作MySQL的實(shí)現(xiàn)示例

    C++操作MySQL的實(shí)現(xiàn)示例

    這篇文章主要介紹了C++操作MySQL的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • C語(yǔ)言超詳細(xì)講解指向函數(shù)的指針

    C語(yǔ)言超詳細(xì)講解指向函數(shù)的指針

    C語(yǔ)言程序在編譯后,每個(gè)函數(shù)都有一個(gè)首地址(也就是函數(shù)第一條指令的地址),這個(gè)地址稱為函數(shù)的指針。可以定義指向函數(shù)的指針變量,使用指針變量間接調(diào)用函數(shù)
    2022-07-07
  • C++中的const的使用詳解

    C++中的const的使用詳解

    這篇文章主要介紹了 C++中的const的使用詳解的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • 詳解C++編程中表達(dá)式的語(yǔ)義與計(jì)算順序

    詳解C++編程中表達(dá)式的語(yǔ)義與計(jì)算順序

    這篇文章主要介紹了C++編程中表達(dá)式的語(yǔ)義與計(jì)算順序,是C++入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2016-01-01
  • C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片

    C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言讀取和存儲(chǔ)bmp格式圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C/C++實(shí)現(xiàn)監(jiān)控目錄文件變化

    C/C++實(shí)現(xiàn)監(jiān)控目錄文件變化

    ReadDirectoryChangesW是Windows操作系統(tǒng)提供的一個(gè)函數(shù),用于監(jiān)視目錄的變化,本文主要為大家介紹了如何使用ReadDirectoryChangesW實(shí)現(xiàn)監(jiān)控目錄文件變化,需要的可以參考下
    2023-11-11
  • C++深入講解哈夫曼樹(shù)

    C++深入講解哈夫曼樹(shù)

    給定N個(gè)權(quán)值作為N個(gè)葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹(shù),若該樹(shù)的帶權(quán)路徑長(zhǎng)度達(dá)到最小,稱這樣的二叉樹(shù)為最優(yōu)二叉樹(shù),也稱為哈夫曼樹(shù)(Huffman Tree)。哈夫曼樹(shù)是帶權(quán)路徑長(zhǎng)度最短的樹(shù),權(quán)值較大的結(jié)點(diǎn)離根較近
    2022-05-05
  • 使用C語(yǔ)言實(shí)現(xiàn)12種排序方法

    使用C語(yǔ)言實(shí)現(xiàn)12種排序方法

    這篇文章主要介紹了用C語(yǔ)言完整實(shí)現(xiàn)12種排序方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • C++ 微信多開(kāi)的實(shí)現(xiàn)

    C++ 微信多開(kāi)的實(shí)現(xiàn)

    本文主要介紹了C++ 微信多開(kāi)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 基于Matlab繪制超絢麗的煙花的過(guò)程詳解

    基于Matlab繪制超絢麗的煙花的過(guò)程詳解

    這篇文章主要為大家介紹了如何利用Matlab繪制超絢麗的煙花,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-02-02

最新評(píng)論