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

Qt 中開啟線程的多種方式小結

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

簡介

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

1. 繼承 QThread 重寫 run 函數

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

2. 繼承 QObject 調用 moveToThread

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

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

3. 繼承 QRunnable 重新 run 函數,結合 QThreadPool 實現線程池

#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;	           		// 構建一個本地的線程池
	threadpool.setMaxThreadCount(3);        // 線程池中最大的線程數
	
    for ( int num = 0; num < 100; ++num )
	{
	    BPrint *print;    					// 循環(huán)構建可在線程池中運行的任務
	    threadpool.start(print);      		// 線程池分配一個線程運行該任務
	    QThread::msleep(1000);
	}
	
	return a.exec();
}

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

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

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

運行結果:
threadfun1 - 1
threadfun2 - 1

threadfun1 - 2
join
detach

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

5. Qt QtConcurrent 之 Run 函數

Concurrent 是并發(fā)的意思,QtConcurrent 是一個命名空間,提供了一些高級的 API,使得所寫的程序可根據計算機的 CPU 核數,自動調整運行的線程數目。這意味著今后編寫的應用程序將在未來部署在多核系統(tǒng)上時繼續(xù)擴展

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

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

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

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

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

2)向該函數傳遞參數

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

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

3) 獲取該函數的計算結果

extern QString Func(const QByteArray &input);

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

4)常量成員函數

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

5)非常量成員函數

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

6)Lambda 表達式

#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);
    
    // 根據三個點自適應模擬條紋
    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);

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

相關文章

  • 使用c++實現OpenCV圖像橫向&縱向拼接

    使用c++實現OpenCV圖像橫向&縱向拼接

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

    基于Qml實現水印工具

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

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

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

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

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

    C語言實現簡單貪吃蛇小游戲

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

    解析c++中的默認operator=操作的詳解

    本篇文章是對c++中的默認operator=操作的應用進行了詳細的分析介紹。需要的朋友參考下
    2013-05-05
  • Linux網絡編程之socket文件傳輸示例

    Linux網絡編程之socket文件傳輸示例

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

    C/C++中extern函數使用詳解

    extern可以置于變量或者函數前,以標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。此外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)境,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 簡單介紹C++編程中派生類的析構函數

    簡單介紹C++編程中派生類的析構函數

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

最新評論

利津县| 康保县| 邹城市| 临夏县| 寿宁县| 南乐县| 德昌县| 德令哈市| 云浮市| 炉霍县| 灵丘县| 平湖市| 梁平县| 米林县| 都安| 富阳市| 荥阳市| 乳山市| 蚌埠市| 吉安市| 闽清县| 隆林| 新源县| 华蓥市| 兴宁市| 抚顺市| 呈贡县| 霍山县| 方山县| 林芝县| 东阳市| 攀枝花市| 福州市| 六枝特区| 通州市| 百色市| 开阳县| 英超| 乐清市| 邵阳县| 崇信县|