Equivalent to asyncio.sleep?
-
Hi,
please is there some way to give up execution of a function for some time, like asyncio.sleep() - i.e. let Qt evaluate the event loop for a while and then return control back to the function?
Example:
have sequence of commands and e.g. one second pauses between them.
CMD_1>sleep>CMD_2>sleep>CMD_3
Either time.sleep() can be used, which would block the UI, or each CMD would set a singleshot timer to start the next command (which is ugly, hard do read and maintain, results in set of independent functions, requires an object to pass variables instead of simple local vars, but would do).
In asyncio, there is this asyncio.sleep() that does exactly what I mean, returns control to the event loop for a while. I achieve this by series of time.sleep's calling event loop eval manually at this moment, to make the UI less blocked, but this is still rather ugly. Sure, a thread is another way, but again really ugly and resource heavy option.Thank You in advance,
Stepan -
Hi,
please is there some way to give up execution of a function for some time, like asyncio.sleep() - i.e. let Qt evaluate the event loop for a while and then return control back to the function?
Example:
have sequence of commands and e.g. one second pauses between them.
CMD_1>sleep>CMD_2>sleep>CMD_3
Either time.sleep() can be used, which would block the UI, or each CMD would set a singleshot timer to start the next command (which is ugly, hard do read and maintain, results in set of independent functions, requires an object to pass variables instead of simple local vars, but would do).
In asyncio, there is this asyncio.sleep() that does exactly what I mean, returns control to the event loop for a while. I achieve this by series of time.sleep's calling event loop eval manually at this moment, to make the UI less blocked, but this is still rather ugly. Sure, a thread is another way, but again really ugly and resource heavy option.Thank You in advance,
Stepan@Stepan-K
Given that you don't want to use approach like singleshot timer. I don't know if there is better equivalent toasyncio.sleep()
(not my area).There are two obvious way of writing a blocking "sleep" inside a function which still allows the Qt event loop to run and then resumes at the next statement in the function:
-
Call
Q[Core]Application::processEvents()
in a loop, exiting after a period of time. If you call it many times without delay it is quite "busy". And in general callingprocessEvents()
is frowned upon. -
Use a local QEventLoop::exec() primed with a singleshot timer signal connected to QEventLoop::quit(). I think this is preferable to
processEvents()
in your own loop.
These do not block like a
sleep()
would. Of course you must be aware that any arriving signals/events will be processed from within your call before returning to the next statement. Which may or may not be OK.Oh and btw, a different approach is to run your "command pipeline" in a secondary thread. Then you can use
sleep()
there. But you have to be careful about shared variable access and you must not access any UI stuff from any secondary thread. -
-
@Stepan-K
Given that you don't want to use approach like singleshot timer. I don't know if there is better equivalent toasyncio.sleep()
(not my area).There are two obvious way of writing a blocking "sleep" inside a function which still allows the Qt event loop to run and then resumes at the next statement in the function:
-
Call
Q[Core]Application::processEvents()
in a loop, exiting after a period of time. If you call it many times without delay it is quite "busy". And in general callingprocessEvents()
is frowned upon. -
Use a local QEventLoop::exec() primed with a singleshot timer signal connected to QEventLoop::quit(). I think this is preferable to
processEvents()
in your own loop.
These do not block like a
sleep()
would. Of course you must be aware that any arriving signals/events will be processed from within your call before returning to the next statement. Which may or may not be OK.Oh and btw, a different approach is to run your "command pipeline" in a secondary thread. Then you can use
sleep()
there. But you have to be careful about shared variable access and you must not access any UI stuff from any secondary thread.@JonB exactly - and thank You!
You didn't find any better solution than I did I can see - a thread, singleshot timer or blocking shot time.sleep() with processEvents() repeated calling.Btw, sleep methods of the Qthread class are blocking I have found, so there likely isn't any difference in using these to an ordinary time.sleep().. also precision is rather limited (about 1/100sec? in Windows minimal - likely related to CPU context switchitng timer, whereas qtimer appears to support much higher precision, which is often important, too -- that may rule pausing done with time.sleep and processEvents() out for some situations and make qtimer and individual function calls for each of steps the only viable option).
Well, maybe there really isn't any nicer way to achieve this type of serial processing in Qt, which is kind of shame - again, this is not a roadblock, just makes the code less readable due to extra logic.
-
-
@JonB exactly - and thank You!
You didn't find any better solution than I did I can see - a thread, singleshot timer or blocking shot time.sleep() with processEvents() repeated calling.Btw, sleep methods of the Qthread class are blocking I have found, so there likely isn't any difference in using these to an ordinary time.sleep().. also precision is rather limited (about 1/100sec? in Windows minimal - likely related to CPU context switchitng timer, whereas qtimer appears to support much higher precision, which is often important, too -- that may rule pausing done with time.sleep and processEvents() out for some situations and make qtimer and individual function calls for each of steps the only viable option).
Well, maybe there really isn't any nicer way to achieve this type of serial processing in Qt, which is kind of shame - again, this is not a roadblock, just makes the code less readable due to extra logic.
@Stepan-K said in Equivalent to asyncio.sleep?:
You didn't find any better solution than I did I can see - a thread, singleshot timer or blocking shot time.sleep() with processEvents() repeated calling.
I did, and told you to use a local
QEventLoop
withexec()
instead ofprocessEvents()
. Don't know why you ignored that. That is really the canonical way of doing a "sleep/pause" with Qt event loop processing still allowed.Btw, sleep methods of the Qthread class are blocking I have found, so there likely isn't any difference in using these to an ordinary time.sleep()..
I don't understand. You use a "sleep" which blocks the thread --- just what you want between your "command pipeline" being executed in a thread --- but that is fine. The main thread still services the event loop. It's fine to block threads.
As for
time.sleep()
precision, if it's not good enough then use aQTimer
. That is what I suggested with theQEventLoop::exec()
approach.