QTimer isActive返回true,但remainingTime返回-1

时间:2018-05-06 16:15:17

标签: c++ qt qtimer

定义一个计时器并在开始时启动:

QTimer *teleTimer;
teleTimer = new QTimer();
QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction1())); 
teleTimer->start(200);

然后在某处停止并调用另一个函数somefunction2()。该功能完成后,计时器再次启动:

if (teleTimer->isActive())
{
    qDebug() << teleTimer->remainingTime();
    teleTimer->stop();
    delete teleTimer;
}
teleTimer = new QTimer();
QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction3())); 
teleTimer->start(200);

但是,teleTimer->isActive()返回true,而teleTimer->remainingTime()返回-1,然后应用程序崩溃了:

Thread 2 Crashed:: QThread
0   org.qt-project.QtCore           0x000000010ed4be3b QObject::killTimer(int) + 27
1   org.qt-project.QtCore           0x000000010ed5a9b9 QTimer::stop() + 25
2   com.yourcompany.QTGCS           0x000000010dffa609 TelemetrySerialWorker::setTelemetryMode(int) + 745 (telemetryserialworker.cpp:114)

那么如何解决这个问题呢?感谢。

更新:此问题已解决。感谢所有的答复。我将尝试下次以良好的格式发布问题。感谢。

2 个答案:

答案 0 :(得分:0)

通过@eyllanesc提供的提示,我的问题终于得到了解决。

一开始,我使用delete teleTimer然后我的程序开始崩溃。那个时候我以为原因是这个函数再次调用时计时器并没有真正停止。然后我改变了我的代码来运行另一个单次计时器,以便它真的有一个计时器停止。

一开始:(坠毁)

void timerSwitch()
{
    if (teleTimer->isActive())
    {
        qDebug() << teleTimer->remainingTime();
        teleTimer->stop();
        delete teleTimer;
    }
    if (mode == 1)
    {
        teleTimer = new QTimer();
        QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction())); 
        teleTimer->start(200);
    }
    else if (mode == 2)
    {
        somefunction2();
    }

}

第一次改变:(崩溃)

void timerSwitch()
{
    if (teleTimer->isActive())
    {
        qDebug() << teleTimer->remainingTime();
        teleTimer->stop();
        delete teleTimer;
    }
    if (mode == 1)
    {
        teleTimer = new QTimer();
        QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction())); 
        teleTimer->start(200);
    }
    else if (mode == 2)
    {
        teleTimer = new QTimer();
        teleTimer.singleshot(..., ..., SLOT(somefunction2()));
    }

}

然后使用@eyllanesc提供的提示,我将代码更改为:

void timerSwitch()
{
    if (teleTimer->isActive())
    {
        qDebug() << teleTimer->remainingTime();
        teleTimer->stop();
        teleTimer->deleteLater();
    }
    if (mode == 1)
    {
        teleTimer = new QTimer();
        QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction())); 
        teleTimer->start(200);
    }
    else if (mode == 2)
    {
        teleTimer = new QTimer();
        teleTimer.singleshot(..., ..., SLOT(somefunction2()));
    }

}

我的程序仍然崩溃。

然后我将代码更改为:

void timerSwitch()
{
    if (teleTimer->isActive())
    {
        qDebug() << teleTimer->remainingTime();
        teleTimer->stop();
        teleTimer->deleteLater();
    }
    if (mode == 1)
    {
        teleTimer = new QTimer();
        QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction())); 
        teleTimer->start(200);
    }
    else if (mode == 2)
    {
        somefunction2();
    }

}

这次我的程序运行正常。我测试了20多次,所有工作正常并没有崩溃。

在此过程中,我的计算机给出的所有理由都与此类似:

Thread 2 Crashed:: QThread
0   org.qt-project.QtCore           0x000000010ed4be3b QObject::killTimer(int) + 27
1   org.qt-project.QtCore           0x000000010ed5a9b9 QTimer::stop() + 25
2   com.yourcompany.QTGCS           0x000000010dffa609 TelemetrySerialWorker::setTelemetryMode(int) + 745 (telemetryserialworker.cpp:114)

我认为错误来自stop(),因为isActive()会返回true,但remainingTime()会返回-1。我的理解是,当调用isActive()时,计时器确实没有以某种方式停止,但是当调用remainingTime()时,计时器停止了。然后我觉得这不应该是那么愚蠢。我仍有疑问,但问题解决了。我有空的时候会更新更多细节。谢谢所有同伴回复我。

答案 1 :(得分:0)

一般来说,如果您按顺序调用函数,最简单的方法是将序列保存在表中,并使用单次定时器。重新创建计时器或连接是很昂贵的。

#include <QtCore>
#include <functional>
#include <initializer_list>

class Sequencer : public QObject {
public:
  using base_class = QObject;
  struct Element {
    int delay = 0;
    std::function<void()> functor;
  };
  explicit Sequencer(QObject *parent = {}) : QObject(parent) {}
  // takes care of initializer list and other compatible initializers
  Sequencer(QVector<Element> init, QObject *parent = {}) : 
    QObject(parent), m_sequence(std::move(init)) {}
  void start(int index = 0) {
    m_it = m_sequence.begin() + index;
    m_timer.start(m_it->delay, this);
  }
  int stop() {
    m_timer.stop();
    return m_it - m_sequence.begin();
  }
protected:
  void timerEvent(QTimerEvent *event) override {
    if (m_timer.timerId() != event->timerId())
      return base_class::timerEvent(event);
    m_it->functor();
    m_it++;
    if (m_it != m_sequence.end())
      m_timer.start(m_it->delay, this);
    else
      m_timer.stop();
  }
private:
  QVector<Element> m_sequence;
  QVector<Element>::const_iterator m_it = m_sequence.begin();     
  QBasicTimer m_timer;
};

您可以像这样使用它,例如:

class MyClass { // can be QObject, but doesn't have to be
  Sequence m_seq{
    {200, [=]{ function1(); }},   // after 200ms delay
    {0,   [=]{ function2(); }},   // after no delay
    {500, [=]{ function3(); }},   // after 500ms delay
    {0,   [=]{ loop(); }}};       // and right away loop the sequence
  void function1();
  void function2();
  void function3();
  void loop() { m_seq.start(); }
public:
  MyClass() {
    m_seq.start();
  }
};