Qt QThread類

參考博客1:QThread詳解
參考博客2:Qt之線程(QThread)
參考博客3:QT 多線程程序設計
參考博客4:Qt之QThread(深入理解)


QThread類提供了一個平臺無關的方式來管理線程涤躲。
一個QThread對象在程序控制中管理一個線程俱尼。線程在run()中開始執(zhí)行律胀。默認情況下欲间,run()通過調用exec()啟動事件循環(huán)并在線程里運行一個Qt的事件循環(huán)办龄。
執(zhí)行結束時呐伞,將會返回run()函數(shù)的執(zhí)行結果。 當線程啟動瘟檩、結束抹缕、終結時,他會通過發(fā)送一個信號來通知你墨辛。你可以通過isFinished()和isrunning來查詢線程的狀態(tài)卓研。
QThread 的兩種使用方法:
1、子類化 QThread(不使用事件循環(huán))睹簇。
這是官方手冊奏赘、例子以及相關書籍中都介紹的一種常用的方法。
a. 子類化 QThread,創(chuàng)建對象太惠,并調用start()函數(shù)
b. 重載 run 函數(shù)磨淌,run函數(shù)內有一個while或for的死循環(huán)(模擬耗時操作)
c. 設置一個標記為來控制死循環(huán)的退出。

2凿渊、子類化 QObject
a. 子類化 QObject
b. 定義槽函數(shù)
c. 將該子類的對象moveToThread到新線程中

若程序退出時梁只,次線程還在運行,未正常退出
我們應該采取合理的措施來優(yōu)雅地結束線程埃脏,一般思路:
發(fā)起線程退出操作搪锣,調用quit()或exit()。
等待線程完全停止彩掐,刪除創(chuàng)建在堆上的對象构舟。
適當?shù)氖褂脀ait()(用于等待線程的退出)和合理的算法。

下面的代碼按照參考博客4(使用Qt5)修改而來堵幽,可在Qt4.8上面運行:
使用的方法1

運行圖.png

WorkerThread.h

#ifndef WORKERTHREAD_H
#define WORKERTHREAD_H

#include <QThread>
#include <QMutex>
#include <QDebug>

class WorkerThread : public QThread
{
    Q_OBJECT

public:
    explicit WorkerThread(QObject *parent = 0)
        : QThread(parent),
          m_bStopped(false)
    {
        qDebug() << "Worker Thread : " << QThread::currentThreadId();
    }

    ~WorkerThread()
    {
        stop();
        quit();
        wait();//
    }

    void stop()
    {
        qDebug() << "Worker Stop Thread : " << QThread::currentThreadId();
        QMutexLocker locker(&m_mutex);
        m_bStopped = true;
    }
protected:
    virtual void run() {
        qDebug() << "Worker Run Thread : " << QThread::currentThreadId();
        int nValue = 0;
        while (nValue < 100)
        {
            // 休眠50毫秒
            msleep(50);
            ++nValue;

            // 準備更新
            emit resultReady(nValue);

            // 檢測是否停止
            {
                QMutexLocker locker(&m_mutex);
                if (m_bStopped)
                    break;
            }
            // locker超出范圍并釋放互斥鎖
        }
    }
signals:
    void resultReady(int value);


private:
    //QMutex互斥鎖 + bool成員變量旁壮,
    bool m_bStopped;
    QMutex m_mutex;

};

#endif // WORKERTHREAD_H

QMyWidget.h

#ifndef QMYWIDGET_H
#define QMYWIDGET_H

#include <QWidget>
#include <QProgressBar>
#include "WorkerThread.h"

class QMyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit QMyWidget(QWidget *parent = 0);
    ~QMyWidget();

private slots:
    // 更新進度
    void handleResults(int value);

    // 開啟線程
    void startThread();

private:
    QProgressBar *m_pProgressBar;
    WorkerThread m_workerThread;
};
#endif

QMyWidget.cpp

#include "QMyWidget.h"
#include <QPushButton>
#include <QVBoxLayout>


QMyWidget:: QMyWidget(QWidget *parent)
        : QWidget(parent)
    {
        qDebug() << "Main Thread : " << QThread::currentThreadId();

        // 創(chuàng)建開始按鈕、進度條
        QPushButton *pStartButton = new QPushButton(this);
        m_pProgressBar = new QProgressBar(this);

        //設置文本谐檀、進度條取值范圍
        pStartButton->setText(QString::fromLocal8Bit("開始"));
        m_pProgressBar->setFixedHeight(25);
        m_pProgressBar->setRange(0, 100);
        m_pProgressBar->setValue(0);

        QVBoxLayout *pLayout = new QVBoxLayout();
        pLayout->addWidget(pStartButton, 0, Qt::AlignHCenter);
        pLayout->addWidget(m_pProgressBar);
        pLayout->setSpacing(50);
        pLayout->setContentsMargins(10, 10, 10, 10);
        setLayout(pLayout);

        // 連接信號槽
        connect(pStartButton, SIGNAL(clicked(bool)), this, SLOT(startThread()));


        connect(&m_workerThread, SIGNAL(resultReady(int)), this, SLOT(handleResults(int)));
        // 線程結束后抡谐,自動銷毀
        //connect(&m_workerThread, SIGNAL(finished()), &m_workerThread, SLOT(deleteLater()));
    }

    QMyWidget::~QMyWidget(){}


    // 更新進度
    void QMyWidget::handleResults(int value)
    {
        qDebug() << "Handle Thread : " << QThread::currentThreadId();
        m_pProgressBar->setValue(value);
    }

    // 開啟線程
    void QMyWidget::startThread()
    {
        if(!m_workerThread.isRunning()){
                m_workerThread.start();
        }
    }

main.cpp

#include <QtGui/QApplication>
#include "QMyWidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QMyWidget w;
    w.show();   
    return a.exec();
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市桐猬,隨后出現(xiàn)的幾起案子麦撵,更是在濱河造成了極大的恐慌,老刑警劉巖溃肪,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件免胃,死亡現(xiàn)場離奇詭異,居然都是意外死亡惫撰,警方通過查閱死者的電腦和手機羔沙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厨钻,“玉大人扼雏,你說我怎么就攤上這事坚嗜。” “怎么了诗充?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵苍蔬,是天一觀的道長。 經常有香客問我蝴蜓,道長碟绑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任茎匠,我火速辦了婚禮格仲,結果婚禮上,老公的妹妹穿的比我還像新娘诵冒。我一直安慰自己抓狭,他們只是感情好,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布造烁。 她就那樣靜靜地躺著否过,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惭蟋。 梳的紋絲不亂的頭發(fā)上苗桂,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天,我揣著相機與錄音告组,去河邊找鬼煤伟。 笑死,一個胖子當著我的面吹牛木缝,可吹牛的內容都是我干的便锨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼我碟,長吁一口氣:“原來是場噩夢啊……” “哼放案!你這毒婦竟也來了?” 一聲冷哼從身側響起矫俺,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吱殉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厘托,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體友雳,經...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年铅匹,在試婚紗的時候發(fā)現(xiàn)自己被綠了押赊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡包斑,死狀恐怖流礁,靈堂內的尸體忽然破棺而出涕俗,到底是詐尸還是另有隱情,我是刑警寧澤崇棠,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站丸卷,受9級特大地震影響枕稀,放射性物質發(fā)生泄漏。R本人自食惡果不足惜谜嫉,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一萎坷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧沐兰,春花似錦哆档、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至比原,卻和暖如春插佛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背量窘。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工雇寇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蚌铜。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓锨侯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親冬殃。 傳聞我的和親對象是個殘疾皇子囚痴,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內容