If the execution time of slot function is greater than the interval of qtimer?
-
slots: /* if it will need 1000ms to finish */ void doBusyThings() { ... ... } QTimer* timer = new QTimer(this); connect(timer, SIGNAL(tiermOut()), this, SLOT(doBusyThings())); timer->start(500);
What happens to
doBusyThings()
?I mean
doBusyThings()
will be pushed into a queue and wait to execute? Or kill the runningdoBusyThings()
and continue to execute the next? -
slots: /* if it will need 1000ms to finish */ void doBusyThings() { ... ... } QTimer* timer = new QTimer(this); connect(timer, SIGNAL(tiermOut()), this, SLOT(doBusyThings())); timer->start(500);
What happens to
doBusyThings()
?I mean
doBusyThings()
will be pushed into a queue and wait to execute? Or kill the runningdoBusyThings()
and continue to execute the next? -
slots: /* if it will need 1000ms to finish */ void doBusyThings() { ... ... } QTimer* timer = new QTimer(this); connect(timer, SIGNAL(tiermOut()), this, SLOT(doBusyThings())); timer->start(500);
What happens to
doBusyThings()
?I mean
doBusyThings()
will be pushed into a queue and wait to execute? Or kill the runningdoBusyThings()
and continue to execute the next?Hi @Limer,
just to add to @J-Hilk: The events will be queued, but during your long slot no events will be processed.
That means, if you resize your window in that time, it will not be redrawn (Except you use ProcessEvents or start a local event loop).
So there are two solutions:
- split doBusyThings() into smaller pieces that take much shorter time to execute
- use a separate thread to execute the long lasting tasks
Regards
-
Hi @Limer,
just to add to @J-Hilk: The events will be queued, but during your long slot no events will be processed.
That means, if you resize your window in that time, it will not be redrawn (Except you use ProcessEvents or start a local event loop).
So there are two solutions:
- split doBusyThings() into smaller pieces that take much shorter time to execute
- use a separate thread to execute the long lasting tasks
Regards
-
Hi @J-Hilk ,
What happens in this case when a QEventLoop is used?
If the execution time exceeds the QTimer delay, the current process will be killed in order to restart one?
What solution can be envisaged so that the process is not killed despite the execution time and the QEventLoop?
-
Hi @J-Hilk ,
What happens in this case when a QEventLoop is used?
If the execution time exceeds the QTimer delay, the current process will be killed in order to restart one?
What solution can be envisaged so that the process is not killed despite the execution time and the QEventLoop?
@Pogot said in If the execution time of slot function is greater than the interval of qtimer?:
the current process will be killed in order to restart one?
What process do you mean? Nothing will be killed. What will happen: the excution of the newer timer events will be delayed until event loop has a chance to be executed again.
QEventLoop executes a local event loop, usually used to wait for soomething. Is usually bad design to use it.
-
Hi @J-Hilk ,
What happens in this case when a QEventLoop is used?
If the execution time exceeds the QTimer delay, the current process will be killed in order to restart one?
What solution can be envisaged so that the process is not killed despite the execution time and the QEventLoop?
@Pogot said in If the execution time of slot function is greater than the interval of qtimer?:
What happens in this case when a QEventLoop is used?
depends where and how.
IIRC a local QEventLoop does not process, naturally, the events of the global/main eventloop.
So the events should still be queued up and stay that way.
If the execution time exceeds the QTimer delay, the current process will be killed in order to restart one?
nothing is killed or restarted everything happens sequentially. Sooo keep an eye out for stack overflows.
What solution can be envisaged so that the process is not killed despite the execution time and the QEventLoop?
I don't know, what exactly do you want to do!?
What does process killed even mean ?
-
Hi @Limer,
just to add to @J-Hilk: The events will be queued, but during your long slot no events will be processed.
That means, if you resize your window in that time, it will not be redrawn (Except you use ProcessEvents or start a local event loop).
So there are two solutions:
- split doBusyThings() into smaller pieces that take much shorter time to execute
- use a separate thread to execute the long lasting tasks
Regards
@aha_1980 said in If the execution time of slot function is greater than the interval of qtimer?:
just to add to @J-Hilk: The events will be queued, but during your long slot no events will be processed.
@aha_1980 , @J-Hilk , @jsulm
I could test this, but initially it seems easiest to just ask you guys. We are talking aboutQTimer
timeout events. Let's say there are no threads or further event loops involved. Let's say the timeout is 1 second. Suppose that the first time the timeout slot is called it performs some blocking operation (e.g.sleep()
or calculation) which takes 10 seconds.According to "The events will be queued" that implies that when the event loop is next allowed to run, 10 seconds later, it will "notice" that 10 seconds have passed and generate 10 new timeout events at that instant. (Because, so far as I know, nothing is happening timer-/event-wise during the 10 seconds the main thread is busy/sleeping.) Is that really the case? I am thinking that having "missed" 10 (or 9) of the timeouts it will not generate them "in retrospect"? Or, does it really look at how much time has passed and generate multiple timeouts for all the "missing" periods, no matter how many there may be?
-
Sorry it's not process if I take the first example I wanted to ask if it killed the running doBusyThings() and run a new one
I'm asking because it's a behaviour I have. A singleShot Qtimer that calls a SLOT.
In the function there is a QEventLoop if at the time of exec() the timer is exceeded in this case the function is stopped and another restarts via the qt_static_metacall function.Thanks
-
@aha_1980 said in If the execution time of slot function is greater than the interval of qtimer?:
just to add to @J-Hilk: The events will be queued, but during your long slot no events will be processed.
@aha_1980 , @J-Hilk , @jsulm
I could test this, but initially it seems easiest to just ask you guys. We are talking aboutQTimer
timeout events. Let's say there are no threads or further event loops involved. Let's say the timeout is 1 second. Suppose that the first time the timeout slot is called it performs some blocking operation (e.g.sleep()
or calculation) which takes 10 seconds.According to "The events will be queued" that implies that when the event loop is next allowed to run, 10 seconds later, it will "notice" that 10 seconds have passed and generate 10 new timeout events at that instant. (Because, so far as I know, nothing is happening timer-/event-wise during the 10 seconds the main thread is busy/sleeping.) Is that really the case? I am thinking that having "missed" 10 (or 9) of the timeouts it will not generate them "in retrospect"? Or, does it really look at how much time has passed and generate multiple timeouts for all the "missing" periods, no matter how many there may be?
@JonB I wasn't sure myself so I did a small example/test myself:
#include <QTimer> #include <QDebug> class TestTimer : public QObject { Q_OBJECT public: explicit TestTimer(QObject *parent = nullptr) : QObject(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &TestTimer::handleTimeout); timer->start(10); } public slots: void handleTimeout() { qDebug() << "Timeout event triggered at" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); qDebug() << "Starting a long operation..."; // Simulate a longer calculation int result = 0; for (int i = 0; i < 2000000000; ++i) { result += i; } qDebug() << "Long operation completed. Result:" << result; } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TestTimer testTimer; return a.exec(); }
Timeout event triggered at "12:16:40.767" Starting a long operation... Long operation completed. Result: 321730048 Timeout event triggered at "12:16:46.064" Starting a long operation...
Contrary to my expectations, no event queue flooding occurred. Fascinating!
-
@JonB I wasn't sure myself so I did a small example/test myself:
#include <QTimer> #include <QDebug> class TestTimer : public QObject { Q_OBJECT public: explicit TestTimer(QObject *parent = nullptr) : QObject(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &TestTimer::handleTimeout); timer->start(10); } public slots: void handleTimeout() { qDebug() << "Timeout event triggered at" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz"); qDebug() << "Starting a long operation..."; // Simulate a longer calculation int result = 0; for (int i = 0; i < 2000000000; ++i) { result += i; } qDebug() << "Long operation completed. Result:" << result; } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TestTimer testTimer; return a.exec(); }
Timeout event triggered at "12:16:40.767" Starting a long operation... Long operation completed. Result: 321730048 Timeout event triggered at "12:16:46.064" Starting a long operation...
Contrary to my expectations, no event queue flooding occurred. Fascinating!
@J-Hilk said in If the execution time of slot function is greater than the interval of qtimer?:
no event queue flooding occurred.
Indeed. But (unless I misunderstand) your output shows that 6 seconds passed in the long operation but only one timeout event was then generated at conclusion. (Please confirm this, it's not 100% clear from what you chose to show?) It did not (seem) to generate the 600 "missing" timeouts.
Assuming that is what you are showing then, as I suspected, all talk earlier about "So the events should still be queued up and stay that way." is, at least for
QTimer
timeouts, not at all the case.... Instead something like "you get a single timeout event on conclusion of a blocking operation no matter how many timeouts should have been generated during the blockage". Which is actually what I expected.QTimer
timeouts work differently from, say, a mouse click or key press, where if I had done multiple ones during the blocking operation I would actually expect to see each one queued and acted on at conclusion. -
@J-Hilk said in If the execution time of slot function is greater than the interval of qtimer?:
no event queue flooding occurred.
Indeed. But (unless I misunderstand) your output shows that 6 seconds passed in the long operation but only one timeout event was then generated at conclusion. (Please confirm this, it's not 100% clear from what you chose to show?) It did not (seem) to generate the 600 "missing" timeouts.
Assuming that is what you are showing then, as I suspected, all talk earlier about "So the events should still be queued up and stay that way." is, at least for
QTimer
timeouts, not at all the case.... Instead something like "you get a single timeout event on conclusion of a blocking operation no matter how many timeouts should have been generated during the blockage". Which is actually what I expected.QTimer
timeouts work differently from, say, a mouse click or key press, where if I had done multiple ones during the blocking operation I would actually expect to see each one queued and acted on at conclusion.Without digging into the code, my explanation for the behavior is the following:
During the event loop, it is checked if a timer is timed out and if that is the case, the slot is called. Timed out means: the current time is greater or equal to the expected timeout time. Then the next timeout time is calculated.
Nevertheless: blocking the event loop is bad behavior and will lead to all kind of problems. Furthermore, with changing implementation the behavior might be totally different in future.
Regards
-
Without digging into the code, my explanation for the behavior is the following:
During the event loop, it is checked if a timer is timed out and if that is the case, the slot is called. Timed out means: the current time is greater or equal to the expected timeout time. Then the next timeout time is calculated.
Nevertheless: blocking the event loop is bad behavior and will lead to all kind of problems. Furthermore, with changing implementation the behavior might be totally different in future.
Regards
@aha_1980 said in If the execution time of slot function is greater than the interval of qtimer?:
During the event loop, it is checked if a timer is timed out and if that is the case, the slot is called. Timed out means: the current time is greater or equal to the expected timeout time. Then the next timeout time is calculated.
Indeed so. So any talk of timeout events (but not others) being queued is incorrect.
-
@aha_1980 said in If the execution time of slot function is greater than the interval of qtimer?:
During the event loop, it is checked if a timer is timed out and if that is the case, the slot is called. Timed out means: the current time is greater or equal to the expected timeout time. Then the next timeout time is calculated.
Indeed so. So any talk of timeout events (but not others) being queued is incorrect.
-
Actually I'm not confident in that statement anymore, I do not know enough about that subject. I only rely on apparently outdated personal experiences :D
-
@JonB yes and no
yes if you have long lasting "thread blocking functions", No, if a QEventLoop or QProcessEvents is used
@J-Hilk
In the discussion here we are using neither. The OP'svoid doBusyThings() { ... ... } QTimer* timer = new QTimer(this); connect(timer, SIGNAL(tiermOut()), this, SLOT(doBusyThings())); timer->start(500);
You wrote:
that depends, do you do sketchy stuff in busyThings, like start a QEventLoop or call ProcessEvents ?
If not, than the timeout events are queued and executed the next eventloop cycle.I am not intending to be picky, perhaps we have the same thing in mind. My point is only: even though the timeout here is 0.5 seconds if
doBusyThings()
takes 10 seconds (and does no event loop or processing) OP will get a single timeout event after 10 seconds not a plural (20) "timeout events are queued". Which could have been the Qt implementation but isn't. OTOH, (I believe) if it's, say, key press events which occur during the 10 seconds they will get all of them upon conclusion as they are genuinely queued. Just so OP is aware. If this is not important to them that is fine :) -
@J-Hilk
In the discussion here we are using neither. The OP'svoid doBusyThings() { ... ... } QTimer* timer = new QTimer(this); connect(timer, SIGNAL(tiermOut()), this, SLOT(doBusyThings())); timer->start(500);
You wrote:
that depends, do you do sketchy stuff in busyThings, like start a QEventLoop or call ProcessEvents ?
If not, than the timeout events are queued and executed the next eventloop cycle.I am not intending to be picky, perhaps we have the same thing in mind. My point is only: even though the timeout here is 0.5 seconds if
doBusyThings()
takes 10 seconds (and does no event loop or processing) OP will get a single timeout event after 10 seconds not a plural (20) "timeout events are queued". Which could have been the Qt implementation but isn't. OTOH, (I believe) if it's, say, key press events which occur during the 10 seconds they will get all of them upon conclusion as they are genuinely queued. Just so OP is aware. If this is not important to them that is fine :)@JonB said in If the execution time of slot function is greater than the interval of qtimer?:
My point is only: even though the timeout here is 0.5 seconds if
doBusyThings()
takes 10 seconds (and does no event loop or processing) OP will get a single timeout event after 10 seconds not a plural (20) "timeout events are queued". Which could have been the Qt implementation but isn't.Emitting a single QTimer::timeout() in the case of a timer overrun is mentioned in the documentation.
https://doc.qt.io/qt-6/qtimer.html#accuracy-and-timer-resolution:All timer types may time out later than expected if the system is busy or unable to provide the requested accuracy. In such a case of timeout overrun, Qt will emit timeout() only once, even if multiple timeouts have expired, and then will resume the original interval.
-
@JonB said in If the execution time of slot function is greater than the interval of qtimer?:
My point is only: even though the timeout here is 0.5 seconds if
doBusyThings()
takes 10 seconds (and does no event loop or processing) OP will get a single timeout event after 10 seconds not a plural (20) "timeout events are queued". Which could have been the Qt implementation but isn't.Emitting a single QTimer::timeout() in the case of a timer overrun is mentioned in the documentation.
https://doc.qt.io/qt-6/qtimer.html#accuracy-and-timer-resolution:All timer types may time out later than expected if the system is busy or unable to provide the requested accuracy. In such a case of timeout overrun, Qt will emit timeout() only once, even if multiple timeouts have expired, and then will resume the original interval.