QtConcurrent异步并发

Qt并发模块

Qt对于多线程开发提供了QThread,这种方式需要使用者重写该类的run()虚函数,或者如果不需要控制run()里面的线程运行逻辑,只是单纯的想跑个线程,就可以直接调用QObject::moveToThread(QThread *thread)接口,这样QObject的派生类中的所有槽函数都会在thread线程中执行。但是这种还是过于繁琐,始终都需要继承指定类增加多余的操作,而不能像std::thread那样直接执行函数。QtConcurrent模块就可以实现类似的操作并且功能更加强大。

QtConcurrent主要用法

1、QtConcurrent::run()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int test(int a)
{
qDebug() << QThread::currentThreadId();
return a * a;
}
void runThreadTest()
{

qDebug() << QThread::currentThreadId();

QFuture<int> result = QtConcurrent::run(test, 10);
// 1 同步

// qDebug() << result.result();
// 2 异步
QFutureWatcher<int> *watch = new QFutureWatcher<int>();
connect(watch, &QFutureWatcher<int>::finished, this, [ watch]() {
qDebug() << watch->future().result();
watch->deleteLater();
});
watch->setFuture(result);
}

这种用法是最基础的,和std::thread基本一致,但是比标准库好的是它可以直接通过QFuture模板类返回函数的运行值,如果直接在后面调用result.result(),这时候它就会一直等待线程结束返回结果,是一个同步操作,这种使用场景感觉很少。然后Qt又提供了一个

QFutureWatcher模板类实现异步获取线程返回值,只需要绑定QFuture同时监听finished信号,在对应槽函数获取结果。这种只适用于QFuture对像中只有一个返回值的情况。

2、QtConcurrent::mapped()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
QList<int> inputList{5, 10, 15};

QFuture<int> result = QtConcurrent::mapped(inputList, test);
QFutureWatcher<int> *watch = new QFutureWatcher<int>();
connect(watch, &QFutureWatcher<int>::finished, this, [ watch]() {
qDebug() << "all finished";
watch->deleteLater();
});
connect(watch, &QFutureWatcher<int>::resultReadyAt, this, [ watch](int resultIndex) {
qDebug() << "index=" << resultIndex << " " << watch->future().resultAt(resultIndex);
});
connect(watch, &QFutureWatcher<int>::progressValueChanged, this, [ watch](int value) {
qDebug() << "progress=" << value;
});
watch->setFuture(result);

mapped可以传入一个序列进去,然后并发调用传入的函数,序列中的每个参数都以const引用传递给函数使用。这种情况下QFuture会存在多个结果,所以需要监听resultReadyAt信号,表示该index对应的线程计算结束,可以取返回值。

2、QtConcurrent::map()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void test(int &a)
{
qDebug() << "a=" << a << " " << QThread::currentThreadId();
a = a * a;

}
QList<int> inputList{5, 10, 15};
void runThreadTest()
{

QFuture<void> result = QtConcurrent::map(inputList, test);
QFutureWatcher<void> *watch = new QFutureWatcher<void>();
connect(watch, &QFutureWatcher<int>::finished, this, [ watch]() {
qDebug() << "all finished" << inputList;
watch->deleteLater();
});
connect(watch, &QFutureWatcher<int>::progressValueChanged, this, [ watch](int value) {
qDebug() << "progress=" << value;
});
watch->setFuture(result);

}

map和mapped的区别在于它指挥返回一个QFuture的对象,也就是说它不会通过resultReadyAt通知你去获取计算的返回值。但是它第一个参数是传非常量引用的形式,所以可以在计算函数中通过引用形式返回结果。

未完待续。。。。。。


QtConcurrent异步并发
http://yoursite.com/2021/10/18/QtConcurrent异步并发/
作者
还在输入
发布于
2021年10月18日
许可协议