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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt QtConcurrent之 Run 函数用法

發(fā)布時(shí)間:2025/1/21 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt QtConcurrent之 Run 函数用法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

概述

Concurrent是并發(fā)的意思,QtConcurrent是一個(gè)命名空間,提供了一些高級(jí)的 API,使得在編寫多線程的時(shí)候,無需使用低級(jí)線程原語,如讀寫鎖,等待條件或信號(hào)。使用QtConcurrent編寫的程序會(huì)根據(jù)可用的處理器內(nèi)核數(shù)自動(dòng)調(diào)整使用的線程數(shù)。這意味著今后編寫的應(yīng)用程序?qū)⒃谖磥聿渴鹪诙嗪讼到y(tǒng)上時(shí)繼續(xù)擴(kuò)展。

而這里要講的是QtConcurrent::run函數(shù)的用法。
函數(shù)原型如下:

QFuture<T> QtConcurrent::run(Function function, ...) QFuture<T> QtConcurrent::run(QThreadPool *pool, Function function, ...)

簡單的說,QtConcurrent::run()函數(shù)會(huì)在一個(gè)單獨(dú)的線程中執(zhí)行,并且該線程取自全局QThreadPool,該函數(shù)的返回值通過QFuture API提供。
請(qǐng)注意:該函數(shù)可能不會(huì)立即運(yùn)行; 函數(shù)只有在線程可用時(shí)才會(huì)運(yùn)行。
通過QtConcurrent::run()返回的QFuture不支持取消、暫停,返回的QFuture只能用于查詢函數(shù)的運(yùn)行/完成狀態(tài)和返回值。

導(dǎo)入模塊

在 C++ API changes 有關(guān)于 Qt Concurrent 的更改說明

Qt Concurrent has been moved from Qt Core to its own module

大致意思就是,Qt Concurrent已經(jīng)從 QtCore 中移除并成為了一個(gè)獨(dú)立的模塊。
所以在使用的時(shí)候需要在工程文件中導(dǎo)入模塊,如下

QT += concurrent

示例

通過一個(gè)簡單的例子來看一下效果

#include "widget.h" #include <QDebug> #include <QThread> #include <QtConcurrent> #include <QFuture>Widget::Widget(QWidget *parent): QWidget(parent) {m_pBtn = new QPushButton("Click me",this);m_pBtn->setGeometry(100,100,220,70);connect(m_pBtn,&QPushButton::clicked,this,&Widget::onBtnClicked); }void func(QString str) {qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread(); }void Widget::onBtnClicked() { #if 0QFuture<void> f1 =QtConcurrent::run(func,QString("aa"));f1.waitForFinished(); #elseQFuture < void > future = QtConcurrent::run([=](){qDebug() << __FUNCTION__ << QThread::currentThreadId() << QThread::currentThread();});QFuture < void > future2 = QtConcurrent::run([=](){qDebug() << __FUNCTION__ << QThread::currentThreadId() << QThread::currentThread();}); #endif }

做了一個(gè)簡單的界面,通過點(diǎn)擊按鈕來調(diào)用 QtConCurrent::run函數(shù)。

這里在按鈕的槽函數(shù)中用了兩種方法來調(diào)用,一種是調(diào)用外部 extern 函數(shù),一種是使用了Lambda函數(shù),兩種方式只是寫法上的不同,結(jié)果都是一樣的。

注意:第一種方法調(diào)用外部函數(shù),如果該函數(shù)是類的成員函數(shù),會(huì)報(bào)以下錯(cuò)誤 : reference to no-static member function must be called…
如下圖:

定義外部函數(shù)

extern void func(QString str);

這里運(yùn)行了第二種方法,Lambda函數(shù)來實(shí)現(xiàn)。
點(diǎn)擊按鈕后輸出以下結(jié)果:

operator() 0x700005df0000 QThread(0x7fe63ccf8420, name = "Thread (pooled)") operator() 0x700005e73000 QThread(0x7fe63cc56630, name = "Thread (pooled)")

連續(xù)調(diào)用兩次,分別在不同的線程中執(zhí)行的,這也就驗(yàn)證了該函數(shù)的作用。

問題來了

看到這兒,一定會(huì)有個(gè)疑問,上面說調(diào)用的函數(shù)必須是外部函數(shù),通過 extern 來定義函數(shù),那么,如果要調(diào)用類的成員函數(shù)怎么辦呢?先來看看 Qt 文檔的介紹。

使用成員函數(shù)

QtConcurrent :: run()也接受指向成員函數(shù)的指針。第一個(gè)參數(shù)必須是一個(gè)const引用或一個(gè)指向該類實(shí)例的指針。const成員函數(shù)一般傳遞 常量引用 (const reference),而非常量成員函數(shù)一般傳遞 指針 (pointer)

例如,在一個(gè)單獨(dú)的線程中調(diào)用QByteArray :: split()(一個(gè)const成員函數(shù))就像這樣完成:

// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread QByteArray bytearray = "hello world"; QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ','); ... QList<QByteArray> result = future.result();

調(diào)用非const成員函數(shù)是這樣完成的:

// call 'void QImage::invertPixels(InvertMode mode)' in a separate thread QImage image = ...; QFuture<void> future = QtConcurrent::run(&image, &QImage::invertPixels, QImage::InvertRgba); ... future.waitForFinished(); // At this point, the pixels in 'image' have been inverted

OK,大概清楚了,我們修改一下上面的示例,讓 QtConCurrent::run去調(diào)用成員函數(shù)。
看代碼:

#include "widget.h" #include <QDebug> #include <QThread> #include <QtConcurrent> #include <QFuture>Widget::Widget(QWidget *parent): QWidget(parent) {m_pBtn = new QPushButton("Click me",this);m_pBtn->setGeometry(100,100,220,70);connect(m_pBtn,&QPushButton::clicked,this,&Widget::onBtnClicked); }void Widget::onBtnClicked() { #if 1//調(diào)用外部函數(shù)QFuture<void> f1 =QtConcurrent::run(func,QString(index++));//調(diào)用類成員函數(shù)QFuture<void> f2 =QtConcurrent::run(this,&Widget::myFunc,QString("aaa")); #else //使用Lambda函數(shù)實(shí)現(xiàn)QFuture < void > future = QtConcurrent::run([=](){qDebug() << __FUNCTION__ << QThread::currentThreadId() << QThread::currentThread();});QFuture < void > future2 = QtConcurrent::run([=](){qDebug() << __FUNCTION__ << QThread::currentThreadId() << QThread::currentThread();}); #endif }void Widget::myFunc(const QString & str) {qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread(); }void func(QString str) {qDebug() << __FUNCTION__ << str << QThread::currentThreadId() << QThread::currentThread(); }

簡單說明一下,這里新增了一個(gè)成員函數(shù)myFunc,在槽函數(shù)onBtnClicked中進(jìn)行調(diào)用。

//調(diào)用類成員函數(shù)QFuture<void> f2 =QtConcurrent::run(this,&Widget::myFunc,QString("aaa"));

使用Lambda函數(shù)

調(diào)用lambda函數(shù)是這樣完成的:

QFuture<void> future = QtConcurrent::run([=]() {// Code in this block will run in another thread }); ...

上面示例中已經(jīng)添加了Lambda 函數(shù)的調(diào)用方法,如果說將要調(diào)用的函數(shù)執(zhí)行的內(nèi)容不多的話 可以考慮使用Lambda 函數(shù),使用會(huì)比較簡單。

參考資料:http://doc.qt.io/qt-5/qtconcurrentrun.html

總結(jié)

以上是生活随笔為你收集整理的Qt QtConcurrent之 Run 函数用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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