C++ 合并并发调用
我有三个方法,它们都返回一个字符串,我想使用C++ 合并并发调用,c++,qt,promise,qt5,C++,Qt,Promise,Qt5,我有三个方法,它们都返回一个字符串,我想使用QtConcurrent运行它们,并将它们返回到一个列表或类似的东西中QtConcurrent::mapped非常理想,因为它返回一个迭代器,但我一次只能运行一个方法。 在JavaScript中有promise.all([method\u a,method\u b,method\u c]),它会自动将它们的返回合并到一个结果(迭代器)中。 如何在Qt中实现这一点?您正在寻找的方法是: QList QFuture::results()const 返回将来
QtConcurrent
运行它们,并将它们返回到一个列表或类似的东西中QtConcurrent::mapped
非常理想,因为它返回一个迭代器,但我一次只能运行一个方法。
在JavaScript中有promise.all([method\u a,method\u b,method\u c])
,它会自动将它们的返回合并到一个结果(迭代器)中。
如何在Qt中实现这一点?您正在寻找的方法是:
QList QFuture::results()const
返回将来的所有结果。如果结果不正确
此功能立即可用,将阻塞并等待它们恢复
变得可用
从Qt自身扩展:
QImage缩放(常量QImage和图像)
{
返回图像。缩放(100100);
}
QList图像=。。。;
QList thumbnails=QtConcurrent::mapped(图像,缩放).results();
因为没有内置的方法来实现这一点,所以您可以自己设计一个类来保持未来,并在所有任务完成后返回结果集合。这里唯一的限制是由于c++的强类型特性:由QtConcurrent::run
返回的每个future都保存被调用的函数结果,其类型在编译时作为QFuture
模板参数给出。如果被调用函数的返回类型彼此不同怎么办?在我提供的示例中,它们都返回相同的类型,但我认为可以使用QVariant
来表示这一意思,并且可以忽略它
在承诺中。h:
并将此回调传递给promise,然后
:
void callback(QVector<int> results)
{
qDebug() << results;
}
以防万一,有人想知道为什么我要加入三个类,而不是直接让
Promise
extendQObject
,并实现finished
插槽本身:Qt不让我这么做。当“代码”> QyObjult< /Cuff>宏被添加到类模板时,将显示一个显式编译器错误:QSobject不支持的模板类。 < P>我知道是一个C++库,它将调用转换成QWORD类型,并将它像JavaScript中的一个承诺对象一样使用(将多个不同类型的期货组合成一个单一的未来对象)。不幸的是,我从来没有用过它!但是关于这个引用Qt Blog有很多细节因为您有几个方法要调用,所以您可以将它们作为一个functor序列作为第一个参数传递给QtConcurrent::mapped
。映射函子将是一个apply
函子,它接受一个表示方法调用的函子并返回调用它的结果
首先,让我们来上课:
// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-combine-49802153
#include <QtConcurrent>
#include <functional>
#include <initializer_list>
#include <type_traits>
class Cls {
public:
QString method1() const { return QStringLiteral("10"); }
QString method2() const { return QStringLiteral("20"); }
QString method3() const { return QStringLiteral("30"); }
};
让我们方便地从要调用的函子序列类型中创建这样的应用程序:
template <class Sequence, class A = apply_t<typename std::decay_t<Sequence>::value_type>>
A make_apply(Sequence &&) { return {}; }
然后,问题变得相当简单。首先,我们创建一个将被调用的绑定方法的向量。然后,我们将要调用的方法以及对其进行操作的应用程序传递给QtConcurrent::mapped
。results()
按顺序列出了方法调用的所有结果
int main() {
Cls obj;
auto const methods = make_vector({
std::bind(&Cls::method1, &obj),
std::bind(&Cls::method2, &obj),
std::bind(&Cls::method3, &obj)
});
QFuture<QString> result =
QtConcurrent::mapped(methods, make_apply(methods));
Q_ASSERT((result.results() == QStringList{"10", "20", "30"}));
}
intmain(){
Cls obj;
自动常量方法=生成向量({
std::bind(&Cls::method1和&obj),
std::bind(&Cls::method2和&obj),
std::bind(&Cls::method3和&obj)
});
未来结果=
QtConcurrent::mapped(方法,make_apply(方法));
Q_断言((result.results()==QStringList{10”,“20”,“30}));
}
我们可以使用包装的lambda来提供
QtConcurrent::mapped
所期望的result\u-type
成员类型,而不是定制apply\t
类。有关包装lambda的详细信息,请参见。提供了这种包装的示例。您不明白我的意思,我想同时调用三种方法,假设有scaled1
,scaled2
,scaled3
,而不仅仅是scaled
。然后像javascript中的promise.all
一样获取所有结果。@MrGisa逐个获取它们并连接。如果返回的是阻塞调用,则使用QVector和append。如果notQtConcurrent
错误,请使用QThread并在线程中所有3个值都可用时将该值作为合并的单个值发送回。没有任何语法可以将所有返回合并到一个值中,而您可以从Perl或Javascript中了解到这些值。@user3606329当然有一个合并操作,QFuture
已经通过results()
方法提供了它!@库巴·奥伯:是的,我知道QFuture::results()
。OP可能需要一行代码来合并3个QT并发调用的结果,并显示了Javascript中的promise.all方法作为参考?这些函数对象可用于向函数调用添加状态。这句话的含义是什么?@Crawl.Wresult\u type
是Method
返回的类型。为了在某些情况下使用,函子(可调用对象)需要有result\u type
type成员,或trait类中的等效类型。
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<QFuture<int>> futures = {
QtConcurrent::run(&f, 1),
QtConcurrent::run(&f, 2),
QtConcurrent::run(&f, 3)
};
Promise<int> promise(futures);
promise.then(callback);
return a.exec();
}
QVector(1, 2, 3)
// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-combine-49802153
#include <QtConcurrent>
#include <functional>
#include <initializer_list>
#include <type_traits>
class Cls {
public:
QString method1() const { return QStringLiteral("10"); }
QString method2() const { return QStringLiteral("20"); }
QString method3() const { return QStringLiteral("30"); }
};
template <class Method> struct apply_t {
using result_type = typename std::result_of_t<Method()>;
auto operator()(Method method) {
return method();
}
};
template <class Sequence, class A = apply_t<typename std::decay_t<Sequence>::value_type>>
A make_apply(Sequence &&) { return {}; }
template <class T> QVector<T> make_vector(std::initializer_list<T> init) {
return {init};
}
int main() {
Cls obj;
auto const methods = make_vector({
std::bind(&Cls::method1, &obj),
std::bind(&Cls::method2, &obj),
std::bind(&Cls::method3, &obj)
});
QFuture<QString> result =
QtConcurrent::mapped(methods, make_apply(methods));
Q_ASSERT((result.results() == QStringList{"10", "20", "30"}));
}