A timer is defined and started in the beginning:
QTimer *teleTimer;
teleTimer = new QTimer();
QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction1()));
teleTimer->start(200);
Then it is stopped somewhere and another function somefunction2()
is called. After that function finished, the timer is started again:
if (teleTimer->isActive())
{
qDebug() << teleTimer->remainingTime();
teleTimer->stop();
delete teleTimer;
}
teleTimer = new QTimer();
QObject::connect(teleTimer, SIGNAL(timeout()), this, SLOT(somefunction3()));
teleTimer->start(200);
However, teleTimer->isActive()
returns true
, while teleTimer->remainingTime()
returns -1
, then the application is crashed:
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)
So how to fix this? Thanks.
Update: This problem is solved. Thanks for all the replies. I will try to post a question in a good format next time. Thanks.
Generally speaking, if you're invoking functions in a sequence, it's simplest to keep the sequence in a table, and use single-shot timers. Recreating timers or connections is expensive.
#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;
};
You'd use it like this, for example:
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();
}
};