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);
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通知你去获取计算的返回值。但是它第一个参数是传非常量引用的形式,所以可以在计算函数中通过引用形式返回结果。
未完待续。。。。。。