如何在特定时间每天发出Qt信号?

6
我需要在新的一天开始时通知一些对象清除它们的缓存。因此,我可以创建QTimer或类似的东西,并检查每个毫秒,现在是否是午夜+-5ms,但这对我来说不是一个好主意。在QT中是否有任何标准机制可以在不分配任何新对象的情况下通知此事件?像qApp这样的自应用程序初始化以来一直存在的静态机制?如果你需要在00:00做一些事情,你会怎么做?
更新: 我正在寻找足够快的解决方案。快速意味着我需要尽可能快地在插槽中清除容器,因为自午夜以来,容器中的数据已变得无效。因此,还有另一个计时器,例如每100毫秒触发一次,并尝试从容器中获取数据。我需要在任何可能尝试访问之前清除具有无效数据的容器。
1个回答

13

最简单的解决方案确实使用计时器。轮询时间的流逝不仅是不必要的,而且在性能方面会非常糟糕。只需在午夜敲响时开始执行操作:

static int msecsTo(const QTime & at) {
  const int msecsPerDay = 24 * 60 * 60 * 1000;
  int msecs = QTime::currentTime().msecsTo(at);
  if (msecs < 0) msecs += msecsPerDay;
  return msecs;
}

// C++11

void runAt(const std::function<void> & job, const QTime & at, Qt::TimerType type = Qt::VeryCoarseTimer) {
  // Timer ownership prevents timer leak when the thread terminates.
  auto timer = new QTimer(QAbstractEventDispatcher::instance());
  timer->start(msecsTo(at), type);
  QObject::connect(timer, &QTimer::timeout, [=job, &timer]{
    job();
    timer->deleteLater();
  });
}  

runAt([&]{ object->member(); }, QTime(...));

// C++98

void scheduleSlotAt(QObject * obj, const char * member, const QTime & at, Qt::TimerType type = Qt::VeryCoarseTimer) {
  QTimer::singleShot(msecsTo(at), type, obj, member);
}

class MyObject : public QObject {
  Q_OBJECT
  void scheduleCleanup() {
    scheduleSlotAt(this, SLOT(atMidnight()), QTime(0, 0));
  }
  Q_SLOT void atMidnight() {
    // do some work here
    ...
    scheduleCleanup();
  }
public:
  MyObject(QObject * parent = 0) : QObject(parent) {
    ...
    scheduleCleanup();
  }
};  

还有另一个计时器,例如每100毫秒触发一次,并尝试从容器中获取数据。

由于这两个计时器可能在同一个线程中运行,它们会依次执行,不管其中哪个“稍后”多久。它们不会同时运行。


谢谢。这是个好答案。希望它能够起作用,但我认为它可能不够快。它会是排队连接还是直接连接? - cassandrad
@cassandradied,连接类型对您来说并不重要。 您每天在指定时间(比如午夜)运行一次。 即使它晚了一分钟,也没有问题。 实际上,它运行的时间已经舍入到最近的秒钟。 您的担忧是完全无意义的。 您必须非常清楚地说明为什么您认为它不够快(以及您所谓的“不够快”是什么意思)。 我认为您基本上误解了Qt工作原理的某些内容。 - Kuba hasn't forgotten Monica
这只是一个好的答案,但对我来说并不是最好的解决方案,所以我没有点赞或标记为接受。请参见更新。是的,我可以通过添加同步变量和定时器来解决我的问题,但我正在寻找其他可能的解决方案。 - cassandrad
@cassandradied 像你说的那样对于“接受”要小心是好的,但通常对于自己问题的答案要慷慨一些,给予“赞同”。如果它是一个好的、诚实的答案提供了解决方案,即使最终没有使用该解决方案,提问者也应该给予赞同。您可以给多个答案点赞,它们不必是“最好”的答案才能得到赞同。 - hyde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接