QtConcurrent::run()多线程的同步、异步

发布时间 2023-12-09 19:19:15作者: 夕西行

Qt 提供了 QtConcurrent 模块,处理一些常见的并行计算,最大的特点就是无需再使用互斥锁这种很低级的操作,全都封装好了。除此以外,QFuture、QFutureWatcher、QFutureSynchronizer 类提供了一些辅助性的操作。参考:Qt 中的多线程技术 - 知乎 (zhihu.com)

【QtConcurrent::run() 需注意】

  • 传参数的时候,都会复制一份副本。即使参数是引用,在函数中修改数据也不会对源对象产生任何影响。
  • QFuture::result() 与 QFuture::waitForFinished()函数都会阻塞,直到结果可用才继续之后的代码。
  • QtConcurrent::run()返回的QFuture不支持取消、暂停和进度报告。返回的QFuture只能用于查询运行/完成状态和函数的返回值。

可以执行无参、含参、有返回值函数,以及lambda表达式。参考Qt多线程编程之高级函数 - 知乎 (zhihu.com) 和 Qt 多线程的几种实现方式 - 知乎 (zhihu.com)

【QFutureWAtcher】

QFuture::result() 会阻塞,若不想一直等待结果,可以使用QFutureWAtcher获取通知。

参考 QT高级线程API总结(一)QtConcrrent::run_qtconcurrent::run(qthreadpool::globalinstance(), [-CSDN博客

QByteArray bytearray = "hello ,world";
QFuture<QString > future = QtConcurrent::run(this, &MainWindow::threadFunc, bytearray);
//QFutureWatcher<QString> *m_watcher = new QFutureWatcher<QString>(this);
m_watcher = new QFutureWatcher<QString>(this);
m_watcher->setFuture(future);
connect(m_watcher, &QFutureWatcher<QString>::finished, [=](){
    qDebug() << "finished";
});
 
QString MainWindow::threadFunc(QByteArray &arg){
    qDebug() << "threadFunc:" << arg;
 
    //do process...
    return QString("");
};

【QFutureSynchronizer】

为了简化多个QFuture的同步等待操作,特地为我们提供了一个模板类QFutureSynchronizer。

参考 使用QFuture类监控异步计算的结果 - findumars - 博客园 (cnblogs.com)

#include <QCoreApplication>
#include <QFuture>
#include <QFutureSynchronizer>
#include <QtConcurrent>
#include <QDebug>

//计算第lindex 个 斐波那契数值
qulonglong Fibonacci(int index)
{
qulonglong f1 = 1, f2 = 1, cur = 0;
for(int i = 3; i <= index; i++)
{
cur = f1 + f2;
f1 = f2;
f2 = cur;
}
return cur;
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QFutureSynchronizer<qulonglong> synchronizer;
synchronizer.addFuture(QtConcurrent::run(Fibonacci, 50));
synchronizer.addFuture(QtConcurrent::run(Fibonacci, 100));
synchronizer.waitForFinished();
qDebug() << "第50个斐波那契数: " << synchronizer.futures()[0].result();
qDebug() << "第100个斐波那契数: " << synchronizer.futures()[1].result();

return a.exec();
}