Inside my async
handler I want to wait until task's state is changed. For now, I just check the state in an endless loop and wait. Here is an example, the wait_until_done
function:
import asyncio
class LongTask:
state = 'PENDING'
my_task = LongTask()
def done():
my_task.state = 'DONE'
async def wait_until_done():
while True:
if my_task.state == 'PENDING':
await asyncio.sleep(2)
else:
break
print("Finally, the task is done")
def main(loop, *args, **kwargs):
asyncio.ensure_future(wait_until_done())
loop.call_later(delay=5, callback=done)
loop = asyncio.get_event_loop()
main(loop)
loop.run_forever()
Is there a better way for doing that?
Just to avoid confusion: I guess you are not talking about asyncio.Task, but some variable state instead, right?
In this case you have Future and synchronization primitives that allows you to wait some thing changed asynchronously.
If you need to switch between two states, asyncio.Event is probably what you want. Here's little examle:
import asyncio
my_task = asyncio.Event()
def done():
my_task.set()
async def wait_until_done():
await my_task.wait() # await until event would be .set()
print("Finally, the task is done")
async def main():
loop.call_later(delay=5, callback=done)
await wait_until_done()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
Upd:
More complex example that keeps LongTask
interface:
import asyncio
class LongTask:
_event = asyncio.Event()
@property
def state(self):
return 'PENDING' if not type(self)._event.is_set() else 'DONE'
@state.setter
def state(self, val):
if val == 'PENDING':
type(self)._event.clear()
elif val == 'DONE':
type(self)._event.set()
else:
raise ValueError('Bad state value.')
async def is_done(self):
return (await type(self)._event.wait())
my_task = LongTask()
def done():
my_task.state = 'DONE'
async def wait_until_done():
await my_task.is_done()
print("Finally, the task is done")
async def main():
loop.call_later(delay=5, callback=done)
await wait_until_done()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
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