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

Qt Multiple Async While Loops and qApp->processEvents();

本文关键字:gt processEvents qApp- 异步 循环 Qt      更新时间:2023-10-16

我正在尝试做一个项目,正在用QT GUI C 5.6.2在窗口上创建一些图形。我有两种名为" createvertilityspeedIndicator"answers" createAieRspeedIndicator"的方法。这些方法需要使用一段时间(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;
}