Is There Any Way To Guarantee Asyncio.task Will Be Started Immediately?
Solution 1:
Looks like I found solution. We need global lock that would suspend second task locked checking while first task starts:
import asyncio
l = asyncio.Lock()
check_lock = asyncio.Lock()
asyncdeftest():
asyncwith check_lock:
print('locked'if l.locked() else'unlocked')
await asyncio.ensure_future(l.acquire())
print('now', 'locked'if l.locked() else'unlocked')
await asyncio.sleep(1)
l.release()
asyncdefmain():
await asyncio.gather(test(), test())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Output:
unlocked
now locked
locked
# 1 second delay here
now locked
But here we get another problem: second task would be suspended while first task completely done, that's why we get 1 second delay before second locking. It was hard to see in original example (because test()
wait for single lock), that's why I added second printing. But it can be important for multiple locking of different resources to start coroutine immediately: we should lock only creating task, but not it's awaiting. Creating task itself wouldn't start that task (and l.acquire()
) immediately, we should return control to event loop. It can be done by await asyncio.sleep(0)
. Here's final solution for original code:
import asyncio
l = asyncio.Lock()
check_lock = asyncio.Lock()
asyncdeftest():
asyncwith check_lock:
print('locked'if l.locked() else'unlocked')
task = asyncio.ensure_future(l.acquire()) # only create taskawait asyncio.sleep(0) # return control to event loop, it allows lock to be locked before task completedprint('now', 'locked'if l.locked() else'unlocked') # would be printed immediatelyawait task # and now we can await for task doneawait asyncio.sleep(1)
l.release()
asyncdefmain():
await asyncio.gather(test(), test())
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Output:
unlocked
now locked
locked
# no delay here
now locked
Post a Comment for "Is There Any Way To Guarantee Asyncio.task Will Be Started Immediately?"