I have multiple QTimer in the same thread, in the slot connected to the QTimer, I use QEventLoop for synchronization, like http requests, but I found different QTimers may affect each other when they are started in different orders.
Here is my simple test code snippet:
Case 1
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTimer t1;
QTimer t2;
QObject::connect(&t1, &QTimer::timeout, []()->void{
qDebug() << QDateTime::currentDateTimeUtc() << "T1...";
QEventLoop loop;
// t1 slot run time 3000ms
QTimer::singleShot(3000, &loop, SLOT(quit()));
loop.exec();
});
QObject::connect(&t2, &QTimer::timeout, []()->void{
qDebug() << QDateTime::currentDateTimeUtc() << "T2...";
QEventLoop loop;
// t2 slot run time 100ms
QTimer::singleShot(100, &loop, SLOT(quit()));
loop.exec();
});
// interval 1000ms, start t1 first and then t2
t1.start(1000);
t2.start(1000);
return a.exec();
}
Output:
QDateTime(2022-03-21 14:00:51.014 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:00:51.016 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:00:54.025 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:00:54.027 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:00:58.018 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:00:58.019 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:01:01.014 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:01:01.015 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:01:04.016 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:01:04.016 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:01:07.019 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:01:07.020 UTC Qt::TimeSpec(UTC)) T1...
From the output, you can see t2 is affected by t1, the actual interval is about 3000~4000ms, both for t1 and t2, I think t2 should not be affected
Case 2
Just change the QTimer start order, but things will become different
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTimer t1;
QTimer t2;
QObject::connect(&t1, &QTimer::timeout, []()->void{
qDebug() << QDateTime::currentDateTimeUtc() << "T1...";
QEventLoop loop;
// t1 slot run time 3000ms
QTimer::singleShot(3000, &loop, SLOT(quit()));
loop.exec();
});
QObject::connect(&t2, &QTimer::timeout, []()->void{
qDebug() << QDateTime::currentDateTimeUtc() << "T2...";
QEventLoop loop;
// t2 slot run time 100ms
QTimer::singleShot(100, &loop, SLOT(quit()));
loop.exec();
});
// interval 1000ms, start t2 first and then t1
t2.start(1000);
t1.start(1000);
return a.exec();
}
Output:
QDateTime(2022-03-21 14:04:53.653 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:04:53.656 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:54.659 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:55.655 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:56.656 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:04:56.656 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:57.664 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:58.657 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:04:59.665 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:04:59.667 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:05:00.660 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:05:01.662 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:05:02.652 UTC Qt::TimeSpec(UTC)) T2...
QDateTime(2022-03-21 14:05:03.650 UTC Qt::TimeSpec(UTC)) T1...
QDateTime(2022-03-21 14:05:03.653 UTC Qt::TimeSpec(UTC)) T2...
Now t1 does not affect t2 any more, actual interval for t1 is about 3000~4000ms, t2 is 1000ms.
I am really confused why different start order will have different results. Could anyone help me to explain this?
Platform: Qt 5.5.0 MinGW 32bit, Windows
IDE: Qt Creator 3.4.2
You can simply run my test code directly in main() and check the test results.
Thanks.
Edit 1:
I am using QEventLoop for sync http request of RESTFul API, like this:
// m_http is QNetworkAccessManager
QNetworkReply *reply = m_http->get(request);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
In timer slot, there is only a sync http request, to poll data periodly. Normally the request will be finished very fast, but sometimes it will cost more than 1000ms if error occurs. My application need to communicate with multiple server at the same time, and each connection have a timer to do the polling, all connection instances are in the same thread, so all timers share the same eventloop. My tests is a simple way to simulate the request, using QTimer::singleShot as the time cost by request. Is there any better way to do sync http request in QT? Using QEventLoop may be not the best.