日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

Qt修炼手册11_多线程编程和QThread类

發(fā)布時(shí)間:2025/3/15 c/c++ 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt修炼手册11_多线程编程和QThread类 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.事件循環(huán)

學(xué)習(xí)QT多線程編程之前,有必要先熟悉事件循環(huán)的概念。 先看一個(gè)單線程界面程序的主函數(shù)代碼: int main(int argc, char* argv[]) {QApplication app(argc, argv);// 構(gòu)造主窗口對(duì)象并顯示MainWindow w;w.show(); // 進(jìn)入事件循環(huán)return app.exec(); }在程序初始化完成后,主線程進(jìn)入main()函數(shù)開(kāi)始執(zhí)行應(yīng)用代碼。一般地,我們在主線程上構(gòu)建界面對(duì)象然后進(jìn)入事件循環(huán)以處理控件繪制、用戶輸入、系統(tǒng)輸出等消息。這就是我們通常說(shuō)的事件驅(qū)動(dòng)模型。 這里需要提一個(gè)問(wèn)題,為什么需要多線程編程?
多線程編程旨在提高人機(jī)交互的感受。主線程承擔(dān)著用戶交互的重任,當(dāng)在主線程上運(yùn)行費(fèi)時(shí)的代碼時(shí),就會(huì)影響用戶的正常操作。所以我們常把一些費(fèi)時(shí)費(fèi)力的計(jì)算工作移出主線程,開(kāi)辟新的線程來(lái)運(yùn)行之。
QThread是QT中用于線程管理的類,調(diào)用一個(gè)QThread對(duì)象的start()方法時(shí),會(huì)創(chuàng)建一個(gè)新的線程并執(zhí)行它的run()方法。默認(rèn)地,run()會(huì)調(diào)用exec()方法進(jìn)入自己的消息循環(huán)中。如下圖所示:
上圖中有主線程、工作線程都是執(zhí)行事件循環(huán),并且注意到主線程內(nèi)部含有thr、w、objs這些QObject對(duì)象(這些對(duì)象都是在主線程上創(chuàng)建的)。主線程的事件循環(huán)負(fù)責(zé)檢測(cè)這些對(duì)象是否有消息要處理,有的話則調(diào)用對(duì)象的slot方法。可以使用QObject::moveToThread方法將某個(gè)對(duì)象移到其他線程中,譬如:
class Worker : public QObject {Q_OBJECT… }void someFunc() {QThread thr = new QThread;Worker worker = new Worker;worker->moveToThread(thr);thr->start();… }如果在主線程上調(diào)用someFunc(),則thr和worker在創(chuàng)建后關(guān)聯(lián)在主線程上,當(dāng)調(diào)用worker-> moveToThread()后,worker對(duì)象關(guān)聯(lián)到了新的線程中,如圖所示:
2.QThread類

2.1 類基礎(chǔ)

QThread類可以不受平臺(tái)影響而實(shí)現(xiàn)線程。QThread提供在程序中可以控制和管理現(xiàn)成的多種成員函數(shù)和信號(hào)/槽。通過(guò)QThread類的成員函數(shù)start()啟動(dòng)線程。 class Worker : public QObject {Q_OBJECT public slots:void doWork(){......} };void MyObject::putWorkerInThread() {Worker *worker = new Worker;QThread *workerThread = new QThread(this);connect(workerThread, &QThread::started, worker, &Worker::doWork);connect(workerThread, &QThread::finished,worker, &Worker::deleteLater);worker->moveToThread(workerThread);//開(kāi)始進(jìn)行事件循環(huán),并發(fā)射信號(hào)workerThread->start();workerThread->start(); }上述代碼中,Worker類的槽啟動(dòng)分離線程時(shí)發(fā)送的信號(hào)線程終止時(shí)發(fā)送的信號(hào)相關(guān)聯(lián)。如果我們啟動(dòng)了線程,就會(huì)調(diào)用Worker類的槽函數(shù)doWork()。
換言之,如果運(yùn)行putWorkerInThread()的函數(shù)start(),那么就相當(dāng)于發(fā)送了線程的啟動(dòng)信號(hào)(QThread::started),根據(jù)定義的信號(hào)-槽,程序就會(huì)調(diào)用與函數(shù)connect()相關(guān)聯(lián)的Worker類的槽函數(shù)doWorker()。如果結(jié)束線程,則自動(dòng)發(fā)送QThread::finished信號(hào),發(fā)送此信號(hào)后,立即釋放Worker使用過(guò)的線程內(nèi)存區(qū)域。

QThread通過(guò)信號(hào)函數(shù)started()和finished()通知開(kāi)始和結(jié)束,并查看線程狀態(tài)。可以確認(rèn)究竟是使用函數(shù)isfinished()信號(hào)終止線程,還是使用函數(shù)isRunning()啟動(dòng)線程。使用函數(shù)exit()和quit()可以結(jié)束線程。

2.2 多線程初步

如果使用多線程,有時(shí)需要等到所有線程終止。此時(shí),使用函數(shù)wait()即可。線程中,使用成員函數(shù)sleep()、msleep()、usleep()可以暫停秒、毫秒及微秒單位的線程。

3.QThread使用的內(nèi)存區(qū)域

QThread使用的內(nèi)存區(qū)域分為線程私有區(qū)域和共享內(nèi)存區(qū)域。線程內(nèi)部使用的寄存器區(qū)域只能在線程內(nèi)部共享。共享數(shù)據(jù)區(qū)域可以訪問(wèn)其他線程。 線程內(nèi)部使用的寄存器和棧區(qū)域如下圖所示:
線程內(nèi)部共享區(qū)域雖然不能訪問(wèn)其他線程,但棧區(qū)域可以在線程間共享。因此,如果實(shí)現(xiàn)多種線程訪問(wèn)棧區(qū)域,需要注意互斥體,讀寫鎖等線程的安全性。

3.多線程編程實(shí)例與解析

widget.h #ifndef WIDGET_H #define WIDGET_H#include <QtWidgets/QWidget> #include "ui_widget.h" #include <QThread> #include <QPushButton> #include <QMutex> class MyThread : public QThread {Q_OBJECT public:MyThread(int num); private:bool threadStop;int number;QMutex mutex; public:void stop(); protected:void run(); }; / class widget : public QWidget {Q_OBJECT public:widget(QWidget *parent = 0);~widget();MyThread *thread1;MyThread *thread2; private slots:void btn_start();void btn_stop();void btn_isRunning();void btn_isFinished(); private:Ui::widgetClass ui; };#endif // WIDGET_Hwidegt.cpp
#include "widget.h" MyThread::MyThread(int num) { number = num; }void MyThread::stop() {threadStop = true;qDebug("[%d] Thread stop", number); }void MyThread::run() {threadStop = false;int i = 0;while(!threadStop){mutex.lock();qDebug("[%d] MyThread %d", number, i);i++;sleep(1);mutex.unlock();} }/// widget::widget(QWidget *parent): QWidget(parent) {ui.setupUi(this);thread1 = new MyThread(1);thread2 = new MyThread(2);QPushButton *btn_start = new QPushButton("START", this);btn_start->setGeometry(10, 10, 80, 40);QPushButton *btn_stop = new QPushButton("STOP", this);btn_stop->setGeometry(100, 10, 80, 40);QPushButton *btn_isRunning = new QPushButton("IsRunning", this);btn_isRunning->setGeometry(200, 10, 100, 40);QPushButton *btn_isFinished = new QPushButton("IsFinished", this);btn_isFinished->setGeometry(310, 10, 100, 40);connect(btn_start, SIGNAL(clicked()), this, SLOT(btn_start()));connect(btn_stop, SIGNAL(clicked()), this, SLOT(btn_stop()));connect(btn_isRunning, SIGNAL(clicked()), this, SLOT(btn_isRunning()));connect(btn_isFinished, SIGNAL(clicked()), this, SLOT(btn_isFinished())); }void widget::btn_start() {thread1->start();thread2->start(); }void widget::btn_stop() {thread1->stop();thread2->stop(); }void widget::btn_isRunning() {if(thread1->isRunning())qDebug("[1] Thread is running");elseqDebug("[1] Thread is not running");if(thread2->isRunning())qDebug("[2] Thread is running");elseqDebug("[2] Thread is not running"); }void widget::btn_isFinished() {if(thread1->isFinished())qDebug("[1] Thread Finish");elseqDebug("[1] Thread not Finish");if(thread2->isFinished())qDebug("[2] Thread Finish");elseqDebug("[2] Thread not Finish"); }widget::~widget() {} 輸出結(jié)果: 代碼分析: 1.QThread信號(hào)與槽
  • 信號(hào):終止線程實(shí)例運(yùn)行發(fā)送信號(hào)(void finished)、啟動(dòng)線程實(shí)例發(fā)送信號(hào)(void started)、結(jié)束線程實(shí)例發(fā)送信號(hào)(void terminated)
  • 槽:線程中止運(yùn)行槽(finished)、線程啟動(dòng)槽(start)、線程結(jié)束槽(terminate)
2.QThread優(yōu)先級(jí) QThread通過(guò)函數(shù)setPriority()設(shè)置優(yōu)先級(jí)。

4.關(guān)于QDebug的一點(diǎn)思考 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

VS2010開(kāi)發(fā)Qt,怎么顯示qDebug信息(添加DOS窗口): ??

總結(jié)

以上是生活随笔為你收集整理的Qt修炼手册11_多线程编程和QThread类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。