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

Qt 中開啟線程的多種方式小結(jié)

 更新時間:2021年09月02日 11:07:54   作者:lucky-billy  
本篇文章就來整理一下 Qt 中使用線程的五種方式,方便后期回顧。前面兩種比較簡單,一筆帶過了,主要介紹后面三種,感興趣的朋友跟隨小編一起看看吧

簡介

在開發(fā)過程中,使用線程是經(jīng)常會遇到的場景,本篇文章就來整理一下 Qt 中使用線程的五種方式,方便后期回顧。前面兩種比較簡單,一筆帶過了,主要介紹后面三種。最后兩種方法博主最喜歡,不需要繼承類,可以直接把需要執(zhí)行的函數(shù)放到線程中去運行

1. 繼承 QThread 重寫 run 函數(shù)

class Thread : public QThread
{
    Q_OBJECT
public:
	virtual void run() override;
}
void Thread::run()
{
	...
}
  • 可調(diào)用 thread.start()啟動線程,會自動調(diào)用 run 函數(shù)
  • 可調(diào)用 thread.isRunning()判斷線程是否已啟動
  • 可調(diào)用 thread.terminate()終止線程
  • 可調(diào)用 thread.wait()等待線程終止

2. 繼承 QObject 調(diào)用 moveToThread

class Test : public QObject
{
    Q_OBJECT
public:
    void test();
}
QThread th;
Test test;
test.moveToThread(&th);

需要注意的是:此方法與繼承 QThread 相比較,繼承 QThread 只有 run 函數(shù)中的操作是在線程中執(zhí)行的,而此方法中所有的成員函數(shù)都是在線程中執(zhí)行

3. 繼承 QRunnable 重新 run 函數(shù),結(jié)合 QThreadPool 實現(xiàn)線程池

#include <QObject>
#include <QRunnable>
#include <QThread>
#include <QThreadPool>
#include <QDebug>

class BPrint : public QRunnable
{
	void run()
	{
	    for ( int count = 0; count < 5; ++count )
	    {
			qDebug() << QThread::currentThread();
			QThread::msleep(1000);
	    }
	}
};

int main(int argc, char *argv[])
{
	QCoreApplication a(argc, argv);
 
	QThreadPool threadpool;	           		// 構(gòu)建一個本地的線程池
	threadpool.setMaxThreadCount(3);        // 線程池中最大的線程數(shù)
	
    for ( int num = 0; num < 100; ++num )
	{
	    BPrint *print;    					// 循環(huán)構(gòu)建可在線程池中運行的任務(wù)
	    threadpool.start(print);      		// 線程池分配一個線程運行該任務(wù)
	    QThread::msleep(1000);
	}
	
	return a.exec();
}

在上述例子當(dāng)中,我們創(chuàng)建的 QRunnable 類型的指針 BPrint *print 是不需要我們手動去回收內(nèi)存的,QThreadPool 在結(jié)束該任務(wù)的執(zhí)行后會將對該內(nèi)存進行清空

有的小伙伴會有疑問,既然有 QThread 線程類了,為啥還要用 QRunnable + QThreadPool 創(chuàng)建線程池的方法來使用線程機制呢,感覺用起來很麻煩啊。所以這里要說明一下此方法的使用場景,當(dāng)線程任務(wù)量非常大的時候,如果頻繁的創(chuàng)建和釋放 QThread 會帶來非常大的內(nèi)存開銷,而線程池則可以有效避免這個問題

還有一個問題需要注意一下,QThread 是集成自 QObject 的,我們通常會使用信號槽與外界進行通信。而 QRunnable 并不是繼承自 QObject 類的,所以他無法使用信號槽機制進行通信。這里推薦兩種方法,一個是使用 QMetaObject::invokeMethod()函數(shù)。另一個是使用多重繼承的方法,自定義類需要同時繼承自 QRunnable 和 QObject

4. 使用 C++ 11 中的 sth::thread

#include <thread>
void threadfun1()
{
    std::cout << "threadfun1 - 1\r\n" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "threadfun1 - 2" << std::endl;
}

void threadfun2(int iParam, std::string sParam)
{
    std::cout << "threadfun2 - 1" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "threadfun2 - 2" << std::endl;
}

int main()
{
    std::thread t1(threadfun1);
    std::thread t2(threadfun2, 10, "abc");
    t1.join();		// 等待線程 t1 執(zhí)行完畢
    std::cout << "join" << std::endl;
    t2.detach();	// 將線程 t2 與主線程分離
    std::cout << "detach" << std::endl;
}

運行結(jié)果:
threadfun1 - 1
threadfun2 - 1

threadfun1 - 2
join
detach

根據(jù)輸出結(jié)果可以得知,t1.join() 會等待t1線程退出后才繼續(xù)往下執(zhí)行,t2.detach() 并不會等待,detach字符輸出后,主函數(shù)退出,threadfun2還未執(zhí)行完成,但是在主線程退出后,t2的線程也被已經(jīng)被強退出

5. Qt QtConcurrent 之 Run 函數(shù)

Concurrent 是并發(fā)的意思,QtConcurrent 是一個命名空間,提供了一些高級的 API,使得所寫的程序可根據(jù)計算機的 CPU 核數(shù),自動調(diào)整運行的線程數(shù)目。這意味著今后編寫的應(yīng)用程序?qū)⒃谖磥聿渴鹪诙嗪讼到y(tǒng)上時繼續(xù)擴展

函數(shù)原型如下:
QFuture<T> QtConcurrent::run(Function function, ...)
QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)

簡單來說,QtConcurrent::run() 函數(shù)會在一個單獨的線程中執(zhí)行,并且該線程取自全局 QThreadPool,該函數(shù)的返回值通過 QFuture API 提供

需要注意的是:
1)該函數(shù)可能不會立即運行; 函數(shù)只有在線程可用時才會運行
2)通過 QtConcurrent::run() 返回的 QFuture 不支持取消、暫停,返回的 QFuture 只能用于查詢函數(shù)的運行/完成狀態(tài)和返回值
3) Qt Concurrent 已經(jīng)從 QtCore 中移除并成為了一個獨立的模塊,所以想要使用 QtConcurrent 需要在 pro 文件中導(dǎo)入模塊:
QT += concurrent

使用方式有以下幾種:
1)將函數(shù)運行在某一個線程中,需要使用 extern

extern void func();
QFuture<void> future = QtConcurrent::run(func);

2)向該函數(shù)傳遞參數(shù)

extern void FuncWithArguments(int arg1, const QString &string);

int integer = ...;
QString string = ...;
// 需要傳遞的參數(shù),則跟在函數(shù)名之后,依次加入
QFuture<void> future = QtConcurrent::run(FuncWithArguments, integer, string);

3) 獲取該函數(shù)的計算結(jié)果

extern QString Func(const QByteArray &input);

QByteArray byte_array = ...;
QFuture<QString> future = QtConcurrent::run(func, byte_array);
...
QString result = future.result();

4)常量成員函數(shù)

QByteArray bytearray = "hello world";
// 在一個單獨的線程中,調(diào)用 QByteArray 的常量成員函數(shù) split(),傳遞給 run() 函數(shù)的參數(shù)是 bytearray
QFuture< QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
...
QList<QByteArray> result = future.result();

5)非常量成員函數(shù)

QImage image = ...;
// 在一個單獨的線程中,調(diào)用 QImage 的非常量成員函數(shù) invertPixels(),傳遞給 run() 函數(shù)的參數(shù)是 &image
QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba);
...
future.waitForFinished();

6)Lambda 表達(dá)式

#include <QFuture>
#include <QtConcurrent>
#include <QThreadPool>

QThreadPool pool;
QFuture<void> future = QtConcurrent::run(&pool, [&](QObject *receiver){
    cv::Mat mat = QYImageProcessing::convertQImageToMat(image);
    cv::Mat center = cv::imread("dynaPhase_center.png");
    
    dynaPhase_alive = QYImageProcessing::getDiffPoint(mat, center);
    
    // 根據(jù)三個點自適應(yīng)模擬條紋
    cv::Mat ret = DynamicCarrier::DC_Adaptive_Simulation(dynaPhase_center, dynaPhase_alive, dynaPhase_align);
    ret = ret*255;
    ret.convertTo(ret, CV_8UC1);
    QImage adaptive = QYImageProcessing::convertMatToQImage(ret);
    
    QYAlignControl *align = static_cast<QYAlignControl *>(receiver);
    align->callQmlGetAlivePoint(adaptive, dynaPhase_alive.x, dynaPhase_alive.y);
}, this);

到此這篇關(guān)于Qt 中開啟線程的五種方式的文章就介紹到這了,更多相關(guān)Qt 線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接

    使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接

    這篇文章主要介紹了使用c++實現(xiàn)OpenCV圖像橫向&縱向拼接,文中有圖像拼接函數(shù),可以實現(xiàn)如“長圖拼接王”這類小程序的類似功能,大家可以將該函數(shù)封裝在軟件中自由使用
    2021-08-08
  • 基于Qml實現(xiàn)水印工具

    基于Qml實現(xiàn)水印工具

    這篇文章主要介紹了如何在?Qml?中實現(xiàn)一個簡單但功能強大的水印工具,包括水印文本的透明度、顏色、字體大小、旋轉(zhuǎn)角度等自定義功能,需要的可以參考下
    2024-12-12
  • 深度理解c++中的this指針

    深度理解c++中的this指針

    這篇文章主要介紹了C++編程指向成員的指針以及this指針的基本使用指南,與C語言一樣,存儲的數(shù)值被解釋成為內(nèi)存里的一個地址,需要的朋友可以參考下。
    2016-07-07
  • 基于c++計算矩形重疊面積代碼實例

    基于c++計算矩形重疊面積代碼實例

    這篇文章主要介紹了基于c++計算矩形重疊面積代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • C語言實現(xiàn)簡單貪吃蛇小游戲

    C語言實現(xiàn)簡單貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)簡單貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • 解析c++中的默認(rèn)operator=操作的詳解

    解析c++中的默認(rèn)operator=操作的詳解

    本篇文章是對c++中的默認(rèn)operator=操作的應(yīng)用進行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • Linux網(wǎng)絡(luò)編程之socket文件傳輸示例

    Linux網(wǎng)絡(luò)編程之socket文件傳輸示例

    這篇文章主要介紹了Linux網(wǎng)絡(luò)編程之socket文件傳輸示例,對于基于Linux平臺的C程序員來說有一定的借鑒價值,需要的朋友可以參考下
    2014-08-08
  • C/C++中extern函數(shù)使用詳解

    C/C++中extern函數(shù)使用詳解

    extern可以置于變量或者函數(shù)前,以標(biāo)示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時在其他模塊中尋找其定義。此外extern也可用來進行鏈接指定
    2022-09-09
  • Linux/Manjaro如何配置Vscode的C/C++編譯環(huán)境

    Linux/Manjaro如何配置Vscode的C/C++編譯環(huán)境

    這篇文章主要介紹了Linux/Manjaro配置Vscode的C/C++編譯環(huán)境,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 簡單介紹C++編程中派生類的析構(gòu)函數(shù)

    簡單介紹C++編程中派生類的析構(gòu)函數(shù)

    這篇文章主要介紹了C++編程中派生類的析構(gòu)函數(shù),析構(gòu)函數(shù)平時一般使用較少,需要的朋友可以參考下
    2015-09-09

最新評論

大石桥市| 福鼎市| 崇义县| 长泰县| 噶尔县| 中西区| 丰城市| 乐平市| 溧阳市| 山丹县| 北宁市| 马尔康县| 怀宁县| 淮安市| 马山县| 西乌珠穆沁旗| 乌审旗| 乐都县| 台南市| 江津市| 黔南| 夏河县| 那坡县| 青岛市| 阿巴嘎旗| 马山县| 彰武县| 连州市| 墨江| 蕲春县| 宕昌县| 自贡市| 宜兴市| 雷山县| 福鼎市| 白玉县| 阿尔山市| 博兴县| 阳城县| 淳安县| 通城县|