Qt QtConcurrent之 Run 函数用法
概述
Concurrent是并發的意思,QtConcurrent是一個命名空間,提供了一些高級的 API,使得在編寫多線程的時候,無需使用低級線程原語,如讀寫鎖,等待條件或信號。使用QtConcurrent編寫的程序會根據可用的處理器內核數自動調整使用的線程數。這意味著今后編寫的應用程序將在未來部署在多核系統上時繼續擴展。
而這里要講的是QtConcurrent::run函數的用法。
函數原型如下:
簡單的說,QtConcurrent::run()函數會在一個單獨的線程中執行,并且該線程取自全局QThreadPool,該函數的返回值通過QFuture API提供。
請注意:該函數可能不會立即運行; 函數只有在線程可用時才會運行。
通過QtConcurrent::run()返回的QFuture不支持取消、暫停,返回的QFuture只能用于查詢函數的運行/完成狀態和返回值。
導入模塊
在 C++ API changes 有關于 Qt Concurrent 的更改說明
Qt Concurrent has been moved from Qt Core to its own module大致意思就是,Qt Concurrent已經從 QtCore 中移除并成為了一個獨立的模塊。
所以在使用的時候需要在工程文件中導入模塊,如下
示例
通過一個簡單的例子來看一下效果
#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 }做了一個簡單的界面,通過點擊按鈕來調用 QtConCurrent::run函數。
這里在按鈕的槽函數中用了兩種方法來調用,一種是調用外部 extern 函數,一種是使用了Lambda函數,兩種方式只是寫法上的不同,結果都是一樣的。
注意:第一種方法調用外部函數,如果該函數是類的成員函數,會報以下錯誤 : reference to no-static member function must be called…
如下圖:
定義外部函數
extern void func(QString str);這里運行了第二種方法,Lambda函數來實現。
點擊按鈕后輸出以下結果:
連續調用兩次,分別在不同的線程中執行的,這也就驗證了該函數的作用。
問題來了
看到這兒,一定會有個疑問,上面說調用的函數必須是外部函數,通過 extern 來定義函數,那么,如果要調用類的成員函數怎么辦呢?先來看看 Qt 文檔的介紹。
使用成員函數
QtConcurrent :: run()也接受指向成員函數的指針。第一個參數必須是一個const引用或一個指向該類實例的指針。const成員函數一般傳遞 常量引用 (const reference),而非常量成員函數一般傳遞 指針 (pointer)
例如,在一個單獨的線程中調用QByteArray :: split()(一個const成員函數)就像這樣完成:
// 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();調用非const成員函數是這樣完成的:
// 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 invertedOK,大概清楚了,我們修改一下上面的示例,讓 QtConCurrent::run去調用成員函數。
看代碼:
簡單說明一下,這里新增了一個成員函數myFunc,在槽函數onBtnClicked中進行調用。
//調用類成員函數QFuture<void> f2 =QtConcurrent::run(this,&Widget::myFunc,QString("aaa"));使用Lambda函數
調用lambda函數是這樣完成的:
QFuture<void> future = QtConcurrent::run([=]() {// Code in this block will run in another thread }); ...上面示例中已經添加了Lambda 函數的調用方法,如果說將要調用的函數執行的內容不多的話 可以考慮使用Lambda 函數,使用會比較簡單。
參考資料:http://doc.qt.io/qt-5/qtconcurrentrun.html
總結
以上是生活随笔為你收集整理的Qt QtConcurrent之 Run 函数用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt之创建并使用共享库
- 下一篇: QML for Android 实现二维