Issue
Let's say I have a background task that's looping through existing orders (doing some manipulations if necessary). Now if I want to add an order, this background task should stop while I'm placing a new order and resume when I am finished.
In pseudo-code:
async def loop_orders():
while True:
do_this()
do_that()
return
async def create_order():
stop_loop_orders()
...
send_order()
resume_loop_orders()
return
I couldn't figure out which of these two is the way to go:
- asyncio.Lock: What is locked? How do I define what should be locked?
- asyncio.Event: The wait() method would "Wait until the event is set." => but I would rather need a "wait if the event is set" functionality.
Solution
You cannot suspend and resume an asyncio task.
You could cancel the task and later create a new one, but this leads to more problems than it solves. Data consistency may be compromised and the new task will not resume exactly where the previous one was interupted.
You could easily make the task wait at some specific point (or points)
async def loop_orders():
while True:
... wait here while paused ...
do_this()
do_that()
but when the create_order
pauses the loop_orders
task, the former must wait until the latter reaches that point where it pauses - the create_order
task requests a pause and the loop_orders
acknowledges.
I made a little demo with two Events
that I named enable
and idle
in an attempt to make the method names .clear
, .set
and .wait
match the logic.
import asyncio
enable = None
idle = None
async def loop_orders():
while True:
idle.set()
await enable.wait()
idle.clear();
print("processing order ... ", end="", flush=True)
await asyncio.sleep(0.7)
print("done")
async def create_order():
enable.clear();
await idle.wait()
print("-- pause start ... ", end="", flush=True)
await asyncio.sleep(2)
print("stop")
enable.set()
async def test():
global enable, idle
enable = asyncio.Event()
enable.set() # initial state = enabled
idle = asyncio.Event()
asyncio.create_task(loop_orders())
await asyncio.sleep(2)
await create_order()
await asyncio.sleep(2)
await create_order()
await asyncio.sleep(1)
print("EXIT")
asyncio.run(test())
Answered By - VPfB
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.