[英]How can I pause & resume a task in asyncio?
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:我无法弄清楚这两个中的哪一个是要走的路:
My first idea was我的第一个想法是
lock = asyncio.Lock()
async def loop_orders():
while True:
if not lock.locked():
do_this()
do_that()
async def create_order():
async with lock:
send_order()
So before sending order it sets lock
so if not lock.locked():
should skip do_this() do_that()
.所以在发送订单之前它会设置
lock
所以if not lock.locked():
应该跳过do_this() do_that()
。 But code can run somewhere inside do_this() do_that()
and then lock.locked()
can't stop it.但是代码可以在
do_this() do_that()
内的某个地方运行,然后lock.locked()
无法阻止它。 So maybe it should be in both所以也许它应该在两者中
lock = asyncio.Lock()
async def loop_orders():
while True:
async with lock:
do_this()
do_that()
async def create_order():
async with lock:
send_order()
This way when it starts sending then it has to wait with do_this() do_that()
.这样,当它开始发送时,它必须等待
do_this() do_that()
。 And when it starts do_this() do_that()
then it has to wait with send_order()
当它开始
do_this() do_that()
然后它必须等待send_order()
BTW:顺便提一句:
If you want to understand it then in normal code it could look like如果你想理解它,那么在普通代码中它可能看起来像
lock = False
async def loop_orders():
global lock
while True:
# wait if `lock` was set `True` in other function(s)
while lock:
pass
# set `True` to block other function(s)
lock = True
do_this()
do_that()
# set `False` to unblock other function(s)
lock = False
async def create_order():
global lock
# wait if `lock` was set `True` in other function(s)
while lock:
pass
# set `True` to block other function(s)
lock = True
send_order()
# set `False` to unblock other function(s)
lock = False
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.但是当
create_order
暂停loop_orders
任务时,前者必须等到后者到达它暂停的点 - create_order
任务请求暂停并且loop_orders
确认。
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.我用我命名为
enable
和idle
两个Events
做了一个小演示,试图使方法名称.clear
、 .set
和.wait
与逻辑匹配。
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())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.