gpt4 book ai didi

c++ - Qt 多个异步 While 循环和 qApp->processEvents();

转载 作者:行者123 更新时间:2023-12-03 12:49:30 25 4
gpt4 key购买 nike

我正在尝试做一个项目,使用 Qt GUI C++ 5.6.2 在窗口上创建一些图形。我有两个名为“createVerticalSpeedIndicator”和“createAirSpeedIndicator”的方法。这些方法需要使用 while(1) 循环创建一些图形并使用 qApp->processEvents();在窗口上,当其中一个正在工作而另一个处于非事件状态时,他们做得很完美。但我需要同时且始终运行它们。

我该怎么做才能同时且始终运行它们。

非常感谢

最佳答案

解决方案是反转控制流。 while() { ... processEvents() ... } 是异步代码中的反模式,因为它假设您拥有控制点,而实际上您没有。您很幸运,没有耗尽堆栈,因为 processEvents 可能会重新进入 createXxx 方法。

这是一个完整的转换示例:

// Input
void Class::createVerticalSpeedIndicator() {
for (int i = 0; i < 100; i ++) {
doStep(i);
QCoreApplication::processEvents();
}
}
// Step 1 - factor out state
void Class::createVerticalSpeedIndicator() {
int i = 0;
while (i < 100) {
doStep(i);
QCoreApplication::processEvents();
i++;
}
};
// Step 2 - convert to continuation form
void Class::createVerticalSpeedIndicator() {
int i = 0;
auto continuation = [=]() mutable {
if (!(i < 100))
return false;
doStep(i);
QCoreApplication::processEvents();
i++;
return true;
};
while (continuation());
};
// Step 3 - execute the continuation asynchronously   
auto Class::createVerticalSpeedIndicator() {
int i = 0;
return async(this, [=]() mutable {
if (!(i < 100))
return false;
doStep(i);
i++; // note the removal of processEvents here
return true;
});
};

template <typename F> void async(QObject * parent, F && continuation) {
auto timer = new QTimer(parent);
timer->start(0);
connect(timer, &QTimer::timeout, [timer, c = std::move(continuation)]{
if (!c())
timer->deleteLater();
});
}

此时,您可以将相同的转换应用于 createAirSpeedIndicator 并在类的构造函数中启动它们:

Class::Class(QWidget * parent) : QWidget(parent) {
...
createVerticalSpeedIndicator();
createAirSpeedIndicator();
}

两个任务都将在主线程中异步且伪并发地运行,即每个任务将交替执行一个步骤。

假设我们想要链接任务,即只有在前一个任务完成后才开始任务。用户代码中的修改可以很简单:

Class::Class(QWidget * parent) : QWidget(parent) {
...
createVerticalSpeedIndicator()
>> createAirSpeedIndicator()
>> someOtherTask();
}

async 函数现在必须返回一个允许建立此类连接的类:

struct TaskTimer {
QTimer * timer;
TaskTimer & operator>>(const TaskTimer & next) {
next.timer->stop();
connect(timer, &QObject::destroyed, next.timer, [timer = next.timer]{
timer->start(0);
});
timer = next.timer;
return *this;
}
};

template <typename F> TaskTimer async(QObject * parent, F && continuation) {
TaskTimer task{new QTimer(parent)};
task.timer->start(0);
connect(task.timer, &QTimer::timeout,
[timer = task.timer, c = std::move(continuation)]{
if (!c())
timer->deleteLater();
});
return task;
}

关于c++ - Qt 多个异步 While 循环和 qApp->processEvents();,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44319577/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com