QTimer isActive возвращает значение true, а оставшееся время возвращает значение -1. - PullRequest
0 голосов
/ 06 мая 2018

Таймер определен и запущен в начале:

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 голосов
/ 07 мая 2018

Вообще говоря, если вы вызываете функции в последовательности, проще всего сохранить последовательность в таблице и использовать таймеры одиночного выстрела. Воссоздание таймеров или соединений стоит дорого.

#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();
  }
};
0 голосов
/ 07 мая 2018

С подсказкой @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(), таймер останавливался. Тогда я почувствовал, что это не должно быть так глупо. У меня все еще есть сомнения, но моя проблема решена. Я обновлю более подробную информацию, когда у меня будет время. Спасибо, все ребята ответили мне.

...