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

Qt線程QtConcurrent模塊的使用

 更新時間:2026年01月05日 10:23:59   作者:Larry_Yanan  
QtConcurrent是Qt特有的一個用于實現(xiàn)并發(fā)任務的模塊,本文主要介紹了Qt線程QtConcurrent模塊的使用,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧

前言

在傳統(tǒng) Qt 多線程開發(fā)中,我們常通過繼承 QThread 或使用 moveToThread 來實現(xiàn)后臺任務。但這種方式需要手動管理線程生命周期、信號槽連接、對象所有權(quán)等,樣板代碼多、易出錯。
而 Qt Concurrent 提供了一種更高層次的抽象:你只關(guān)心“做什么”,不關(guān)心“在哪做”。它基于線程池自動調(diào)度任務,極大簡化了并發(fā)編程。
QtConcurrent是Qt特有的一個用于實現(xiàn)并發(fā)任務的模塊,提供了一組基于任務(task-based)而非線程(thread-based)的并發(fā)API。它底層使用 QThreadPool + QRunnable 實現(xiàn),自動管理線程池,你無需手動創(chuàng)建/銷毀線程。如果有一個或多個短期簡單任務會造成主線程的阻塞,又覺得為了他單獨設計一個任務類再移動到子線程太過繁瑣,我們可以使用QtConcurrent。

一、QtConcurrent::run()

QtConcurrent::run()是最簡單的單任務線程實現(xiàn)。在寫具體代碼之前,我們需要先在pro文件中添加相應模塊:

QT += concurrent

然后添加頭文件:

#include <QtConcurrent>

和之前一樣,通過點擊界面按鈕觸發(fā)測試代碼:

int compute(int a, int b) {
    QThread::msleep(500);
    return a + b;
}

void MainWindow::on_btn_thread_start_3_clicked()
{
    static int a = 10, b = 20;
    a++;
    b++;

    // 1?? 啟動異步任務
    QFuture<int> future = QtConcurrent::run(compute, a, b);

    // 2?? 創(chuàng)建 watcher 監(jiān)聽完成事件
    QFutureWatcher<int> *watcher = new QFutureWatcher<int>(this);
    
    // 3?? 連接 finished 信號(在主線程觸發(fā)?。?
    connect(watcher, &QFutureWatcher<int>::finished, this, [watcher]() {
        qDebug() << "Result:" << watcher->result();
        watcher->deleteLater(); // 自動清理內(nèi)存
    });

    // 4?? 將 future 綁定到 watcher
    watcher->setFuture(future);
}

啟動任務的時候,需要傳遞任務函數(shù)和參數(shù):

QFuture<int> future = QtConcurrent::run(compute, a, b);

返回值是第一個可監(jiān)聽的對象,代表一個未來會得到的的結(jié)果。
這一步是同步不阻塞的,隨后我們要馬上對future對象進行觀察。注意QFuture本身是沒有信號的,因此無法使用信號槽。所以我們要單獨設置一個QFutureWatcher來進行觀察,最后綁定future。代碼比較簡單,就不詳細說了。注意watcher要在最終的槽函數(shù)中析構(gòu)哦。
可以看到compute任務函數(shù)中,除了簡單的加法運算之外,還特意做了線程延時。
最后,我們運行代碼:

每次點擊都會疊加運算,并且界面完全不阻塞。
這種寫法特別適合做簡單但有可能造成阻塞的任務,相比于特意重載QThread或使用moveToThread,簡直是清爽多了。(以前工作不太懂,所以也沒用過,實在可惜。)
結(jié)合我過往的開發(fā)經(jīng)驗,說幾個可能的應用場景:
(1)批量加載:本地有多個圖片文件需要加載讀取,甚至還要進行尺寸壓縮
(2)多點繪圖:QImage中需要繪制多線段,這常常伴隨鼠標滑動繪圖,為了不阻塞主線程影響流暢度,應當考慮線程。

二、QtConcurrent::mapped()

除此之外,QtConcurrent也提供了其他的方式,比如QtConcurrent::mapped()(并行轉(zhuǎn)換)和 QtConcurrent::filtered()(并行過濾)。
我嘗試了mapped的方式,它是一種批量的線程實現(xiàn),在某些場合下挺實用的。
接下來,嘗試一下圖片的批量加載,并進行灰度轉(zhuǎn)換,最后彈窗顯示出來。
代碼如下:

QImage convertToGrayscale(const QString& filePath)
{
    // 模擬阻塞
    QThread::msleep(2000);
    QImage img(filePath);
    if (img.isNull()) {
        qWarning() << "Failed to load:" << filePath;
        return QImage(); // 返回空圖
    }
    // 轉(zhuǎn)為黑白(灰度)
    return img.convertToFormat(QImage::Format_Grayscale8);
}

void MainWindow::on_btn_thread_start_3_1_clicked()
{
    // 1. 選擇多個圖片文件(最多10個)
    QStringList filePaths = QFileDialog::getOpenFileNames(
        this,
        "選擇圖片(最多10張)",
        QDir::homePath(),
        "Images (*.png *.jpg *.jpeg *.bmp *.gif)"
        );

    if (filePaths.isEmpty()) {
        return;
    }

    if (filePaths.size() > 10) {
        QMessageBox::warning(this, "警告", "最多只能選擇10張圖片!");
        filePaths = filePaths.mid(0, 10);
    }

    // 2. 禁用按鈕,防止重復點擊
    // m_convertButton->setEnabled(false);

    // 3. 啟動并發(fā)轉(zhuǎn)換
    QFuture<QImage> future = QtConcurrent::mapped(filePaths, convertToGrayscale);

    // 4. 設置 watcher 監(jiān)聽完成
    if (!m_watcher) {
        m_watcher = new QFutureWatcher<QImage>(this);
        connect(m_watcher, &QFutureWatcher<QImage>::finished,
                this, &MainWindow::onConversionFinished);
    }
    m_watcher->setFuture(future);
}

void MainWindow::onConversionFinished()
{
    // 5. 獲取所有結(jié)果(順序與輸入 filePaths 一致)
    QList<QImage> results = m_watcher->future().results();

    // 6. 為每張有效圖片彈窗顯示
    int validCount = 0;
    for (int i = 0; i < results.size(); ++i) {
        if (!results[i].isNull()) {
            QString title = QString("結(jié)果 %1").arg(++validCount);
            showImageInDialog(results[i], title);
        }
    }

    // 7. 恢復按鈕
    // m_convertButton->setEnabled(true);

    if (validCount == 0) {
        QMessageBox::information(this, "提示", "沒有成功加載任何圖片。");
    }
}

void MainWindow::showImageInDialog(const QImage &img, const QString &title)
{
    QDialog* dialog = new QDialog(this);
    dialog->setAttribute(Qt::WA_DeleteOnClose); // 關(guān)閉時自動 delete
    dialog->setWindowTitle(title);
    dialog->resize(600, 400);

    QLabel* label = new QLabel(dialog);
    label->setPixmap(QPixmap::fromImage(img).scaled(
        dialog->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    label->setAlignment(Qt::AlignCenter);

    QVBoxLayout* layout = new QVBoxLayout(dialog);
    layout->addWidget(label);
    dialog->setLayout(layout);

    dialog->show();
}

我們關(guān)注一下這里:

QFuture<QImage> future = QtConcurrent::mapped(filePaths, convertToGrayscale);

先是參數(shù),后是接口,這一點與run有區(qū)別。接口的參數(shù)是QString,但傳遞的參數(shù)卻是QStringList,也就是說qt會自動幫我們適應,處理批量線程??梢钥吹椒祷刂狄琅f是QFuture,它的參數(shù)是QImage,而不是批量的QList<QImage>,這一點要注意哦。
同樣的任務函數(shù)做了一點延時模擬阻塞,順便轉(zhuǎn)換了下灰度。
最后就是完成的槽函數(shù),這代表所有任務都已經(jīng)完成。

QList<QImage> results = m_watcher->future().results();

返回值可以通過results接口獲取。之后就是常規(guī)的彈窗,就不多解釋了。
運行代碼,查看結(jié)果:

在延時的兩秒時間內(nèi),界面完全沒有被阻塞,隨后三個彈窗一起彈出來,效果還是很好的。

三、總結(jié)

有關(guān)QtConcurrent的其他接口測試就先忽略了。光是run和mapped兩種方式,我就已經(jīng)覺得非常實用了。

以下是QtConcurrent和QThread+Worker的對比:

可以看到,QtConcurrent更適合用作一次性的計算任務,特別是簡單一次性的并行任務。如果是需要長期運行的任務,如while循環(huán)獲取,還是采用QThread+Worker比較好。

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

相關(guān)文章

  • C++函數(shù)對象詳解附帶實例

    C++函數(shù)對象詳解附帶實例

    這篇文章主要介紹了C++函數(shù)對象詳解附帶實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • C/C++實現(xiàn)的MD5哈希校驗的示例代碼

    C/C++實現(xiàn)的MD5哈希校驗的示例代碼

    MD5算法是一種廣泛使用的 Hash 算法,常用于確保信息傳輸?shù)耐暾耘c一致性,本文主要介紹了C/C++實現(xiàn)的MD5哈希校驗的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • C語言編寫洗牌發(fā)牌程序

    C語言編寫洗牌發(fā)牌程序

    這篇文章主要為大家詳細介紹了C語言編寫洗牌發(fā)牌程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 簡單談談C++ 頭文件系列之(algorithm)

    簡單談談C++ 頭文件系列之(algorithm)

    <algorithm>是c++特有的STL模板的算法頭文件 包含了一些特定的算法函數(shù) 包括sort(),stable_sort(),partical_sort(),nth_element()等常用的算法函數(shù)
    2017-02-02
  • C++ Primer 第一部分基本語言

    C++ Primer 第一部分基本語言

    這篇文章主要介紹了C++ Primer 第一部分基本語言的相關(guān)資料,需要的朋友可以參考下
    2014-02-02
  • C++模擬實現(xiàn)List迭代器詳解

    C++模擬實現(xiàn)List迭代器詳解

    list不同于其他容器,他是一個鏈表,物理地址并不連續(xù)。所以在實現(xiàn)list類的迭代器的時候,需要將迭代器單獨封裝到一個類里,因為需要重載很多操作符來跟其他容器的迭代器使用達成一致
    2022-04-04
  • 在vs2017上配置AppGameKit庫的圖文教程

    在vs2017上配置AppGameKit庫的圖文教程

    這篇文章主要介紹了在vs2017上配置AppGameKit庫的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • C語言之預處理命令的深入講解

    C語言之預處理命令的深入講解

    這篇文章主要給大家介紹了關(guān)于C語言之預處理命令的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • C 二分查找 遞歸與非遞歸的實現(xiàn)代碼

    C 二分查找 遞歸與非遞歸的實現(xiàn)代碼

    C 二分查找 遞歸與非遞歸的實現(xiàn)代碼,需要的朋友可以參考一下
    2013-03-03
  • C++實現(xiàn)學校人員管理系統(tǒng)

    C++實現(xiàn)學校人員管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)學校人員管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評論

清新县| 夹江县| 昆山市| 城口县| 平谷区| 博乐市| 江源县| 荃湾区| 信丰县| 育儿| 赤水市| 华安县| 斗六市| 班戈县| 肥西县| 金川县| 额敏县| 南陵县| 德兴市| 垣曲县| 沁源县| 五莲县| 刚察县| 丰镇市| 霍邱县| 阿鲁科尔沁旗| 大理市| 龙里县| 什邡市| 澄迈县| 泗水县| 布尔津县| 河南省| 曲麻莱县| 普兰县| 鹤峰县| 漳州市| 库车县| 湟源县| 瑞安市| 积石山|