I have a class with a method that looks like this:
# self.stop_event -> threading.Event
def run(self):
while not self.stop_event.wait(3): # i.e. repeat every 3 sec
pass # do stuff
The idea is that several of these are run in their own thread and at some point one thread does stop_event.set()
, which naturally stops all others. I want to switch to asyncio for this, because the tasks in run
are mostly sleeping and doing IO. Thus, I got to:
# self.stop_event -> asyncio.Event
async def run(self):
while not self.stop_event.is_set():
await asyncio.sleep(3)
pass # do stuff
The problem is that the asyncio.Event
cannot be waited on, so when it is set, there are at most 3 seconds to wait before the method completes. This is a problem, because the sleep time may be minutes. Currently, I am working around this by wrapping the run
in an asyncio.Task
and then cancelling it like event_loop.call_soon(the_task.cancel)
.
I want to ask if there is a better way to achieve the above? Is there a way I can wait on an asyncio.Event
with a timeout somehow, similar to the threading.Event
?
An asyncio event can be used to notify multiple asyncio tasks that some event has happened. An Event object manages an internal flag that can be set to true with the set() method and reset to false with the clear() method. The wait() method blocks until the flag is set to true.
Run an asyncio Event Loop run_until_complete(<some Future object>) – this function runs a given Future object, usually a coroutine defined by the async / await pattern, until it's complete. run_forever() – this function runs the loop forever. stop() – the stop function stops a running loop.
asyncio. wait just waits on the futures. And instead of giving you the results directly, it gives done and pending tasks. You have to manually collect the values. Moreover, you could specify to wait for all futures to finish or just the first one with wait .
2) asyncio. Lock() is used to protect critical sections that call "yield from" - there is no need to use the lock otherwise. The discussion is under assumption of single-threaded asyncio usage mode.
Is there a way I can wait on an
asyncio.Event
with a timeout somehow, similar to thethreading.Event
?
asyncio.wait_for
supports conveniently adding timeouts to any awaited coroutine. An emulation of the timeout feature of threading.Event.wait
for asyncio.Event
could look like this:
async def event_wait(evt, timeout):
# suppress TimeoutError because we'll return False in case of timeout
with contextlib.suppress(asyncio.TimeoutError):
await asyncio.wait_for(evt.wait(), timeout)
return evt.is_set()
This allows a run
almost exactly like the one that used threading.Event
:
async def run(self):
while not await event_wait(self.stop_event, 3):
pass # do stuff
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With