最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt線程QThread開啟和安全退出的實現(xiàn)

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

1、線程開啟

Qt中,開啟子線程,一般有兩種方法:

a, 定義工作類worker:

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

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

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

b, 定義工作類worker:

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

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

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

2、線程關(guān)閉

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

最簡單的方法是添加一個bool變量,通過主線程修改這個bool變量來進行終止,但這樣有可能引起訪問沖突,需要對其進行加鎖。

void myThread::run()
{
    int count = 0;
    m_isCanRun = true;//標記可以運行
    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);// 此處加鎖,防止訪問沖突
            if(!m_isCanRun)//在每次循環(huán)判斷是否可以運行,如果不行就退出循環(huán)
            {
                return;
            }
        }
    }
}

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

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

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

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

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

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

  • 一個是QThread的finished信號對接QObject的deleteLater使得線程結(jié)束后,繼承QObject的那個多線程類會自己銷毀
  • 另一個是QThread的finished信號對接QThread自己的deleteLater,這個不是必須,下面官方例子就沒這樣做:
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)建多線程的方法如下:

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

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

相關(guān)文章

  • C語言鏈表詳解及代碼分析

    C語言鏈表詳解及代碼分析

    這篇文章主要介紹了C語言鏈表詳解及代碼分析,說明了鏈表的定義與概念,通過詳細的代碼展示了基于鏈表的增刪改查功能,希望本文能對你有所幫助
    2021-06-06
  • 簡單講解哈希表

    簡單講解哈希表

    本文主要介紹了哈希表簡單知識及C語言實現(xiàn)哈希表實例,文中利用圖片以及代碼簡單講解了相關(guān)知識,感興趣的小伙伴可以多多學習這篇文章
    2021-09-09
  • C++之初識多態(tài)(Visual Studio 2019)的使用

    C++之初識多態(tài)(Visual Studio 2019)的使用

    文章主要解釋了C++中的多態(tài)概念、實現(xiàn)細節(jié)及一些相關(guān)特性,如虛函數(shù)、override和final關(guān)鍵字、純虛函數(shù)和抽象類,通過代碼示例展示了多態(tài)原理,包括虛函數(shù)表和動態(tài)綁定的概念,并探討了多繼承下虛函數(shù)表的行為
    2026-04-04
  • opencv3.0識別并提取圖形中的矩形的方法

    opencv3.0識別并提取圖形中的矩形的方法

    這篇文章主要介紹了opencv3.0識別并提取圖形中的矩形的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-07-07
  • C++11中std::function基礎(chǔ)用法詳解

    C++11中std::function基礎(chǔ)用法詳解

    std::function是C++11標準庫中提供的一種可調(diào)用對象的通用類型,它可以存儲任意可調(diào)用對象,本文就來和大家講講它的基礎(chǔ)用法,希望對大家有所幫助
    2023-04-04
  • Opencv LBPH人臉識別算法詳解

    Opencv LBPH人臉識別算法詳解

    這篇文章主要為大家詳細介紹了Opencv LBPH人臉識別算法的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C語言實現(xiàn)數(shù)組移位、前移、后移與整體移動實例代碼

    C語言實現(xiàn)數(shù)組移位、前移、后移與整體移動實例代碼

    C語言中通常可以使用循環(huán)語句實現(xiàn)數(shù)組的移動,下面這篇文章主要給大家介紹了關(guān)于C語言實現(xiàn)數(shù)組移位、前移、后移與整體移動的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • C語言全方位講解指針與地址和數(shù)組函數(shù)堆空間的關(guān)系

    C語言全方位講解指針與地址和數(shù)組函數(shù)堆空間的關(guān)系

    指針是C語言中一個非常重要的概念,也是C語言的特色之一。使用指針可以對復雜數(shù)據(jù)進行處理,能對計算機的內(nèi)存分配進行控制,在函數(shù)調(diào)用中使用指針還可以返回多個值
    2022-04-04
  • C++中四種強制轉(zhuǎn)換方式的區(qū)別

    C++中四種強制轉(zhuǎn)換方式的區(qū)別

    在C++中,有四種不同的強制轉(zhuǎn)換方式,它們分別是靜態(tài)轉(zhuǎn)換、動態(tài)轉(zhuǎn)換、常量轉(zhuǎn)換和重新解釋轉(zhuǎn)換,下面通過示例代碼講解每種轉(zhuǎn)換的區(qū)別,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • C++迷宮的實現(xiàn)代碼

    C++迷宮的實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了C++實現(xiàn)迷宮游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論

新和县| 威信县| 浪卡子县| 隆安县| 辰溪县| 理塘县| 赞皇县| 建始县| 凌海市| 亳州市| 曲麻莱县| 高台县| 巢湖市| 孝义市| 朝阳县| 麻城市| 巩留县| 丽水市| 长春市| 安龙县| 江山市| 藁城市| 宝清县| 石台县| 鹿邑县| 民县| 汨罗市| 庆城县| 梅河口市| 临湘市| 兴仁县| 泌阳县| 文山县| 田阳县| 虎林市| 新安县| 新兴县| 柘荣县| 石首市| 凤阳县| 榕江县|