我是 C++ 和 QT 世界的新手。我需要对现有控制台应用程序进行一些修改。
我有以下问题:我同时运行一些功能(需要一些时间)并在这段时间内显示等待指示器。设置如下所示:
QFuture<void> doStuff = QtConcurrent::run(longCalc, param1, param2);
showWaitIndicator(&doStuff);
// ....
void showWaitIndicator(QFuture<void> *future)
{
while (future->isRunning()) {
// Show some nice indicator and so on.
}
}
这个设置工作得很好,但现在我想同时运行一些其他的任务,这些任务有另一个返回类型,我需要访问结果。而不是 QFuture<void>
这些主要是QFuture<double>
, QFuture<int>
等:QFuture<double> doStuff = QtConcurrent::run(doubleCalc);
我也想显示我漂亮的等待指示器,但不同的返回类型意味着我不能使用我当前的 showWaitIndicator()
功能。
有什么好的方法可以改进这个“设置”吗?我是 C++ 的新手,所以我很确定一定有办法。我的第一个想法是函数重载,但这没有用,因为参数具有相同的类型 (QFuture)。
TL;DR:我需要通知我的 showWaitIndicator()
QFuture 完成的函数。
最佳答案
您可以从并发运行的函数发出自定义信号,或使用 QFutureWatcher
作为此类信号的来源。
例如当 longCalc
在同一个类中时:
MyClass::MyClass() {
Q_OBJECT
Q_SIGNAL void longCalcDone();
connect(this, &MyClass::longCalcDone, this, [this]{
...
});
}
void MyClass::longCalc(int arg1, int arg2) {
...
emit MyClass::longCalcDone();
}
例如当 longCalc
是自由函数或在另一个类中时:
void longCalc(int, int);
MyClass::MyClass() {
Q_OBJECT
Q_SIGNAL void longCalcDone();
connect(this, &MyClass::longCalcDone, this, [this]{
...
});
void doStuff() {
QtConcurrent::run([=]{
longCalc(param1, param2);
emit longCalcDone();
});
}
}
例如取而代之的是 future 的观察者:
class MyClass : public QObject {
QFutureWatcher watcher;
MyClass() {
connect(&watcher, &QFutureWatcher::finished, this, [this]{
...
});
}
void doStuff() {
auto future = QtConcurrent::run(longCalc, this, param1, param2);
watcher.setFuture(&future);
}
};
while (future->isRunning())
同步代码是一种反模式。大概您在该循环中调用了 QCoreApplication::processEvents
。问题是——世界不是那样的,你不能把控制点从事件循环中移开,假装世界围绕着你转。相反,反转控制流并在 future 完成时调用您的代码(槽、方法或仿函数)。
另见 this question .
关于c++ - Qt并发: Inform another function that result is ready,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44468849/