I python示例(https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel),一个任务可以像下面的代码片段中一样取消:
task.cancel()
try:
await task
except asyncio.CancelledError:
print("main(): cancel_me is cancelled now")
但是当任务本身被取消与取消另一个任务相同时,这可能会导致竞争条件。
我已经添加了一个通过一个addition await语句导致此问题的示例await asyncio.sleep(0)
import asyncio
async def subtask(i: int):
try:
print(f" subtask {i}: start")
await asyncio.sleep(2)
except asyncio.CancelledError:
print(f" subtask {i}: Clean Up")
raise
async def handling():
i = 0
while True:
print(f" handling {i}: start")
sub_task = asyncio.create_task(subtask(i))
await asyncio.sleep(1)
print(f" handling {i}: cancel subtask")
sub_task.cancel() # (1) There is a reason why subtask must be canceled, but another must be restarted.
try:
await sub_task # (2)
except asyncio.CancelledError:
print(f" handling {i}: subtask canceled {sub_task.cancelled()}")
print(f" handling {i}: end")
i += 1
async def main():
print("main: start")
handling_task = asyncio.create_task(handling())
await asyncio.sleep(1)
await asyncio.sleep(0) # (3) This addition await call forces that handling_task is cancel at the same as calling (2)
print("main: cancel")
handling_task.cancel() # handling_task must be canceled by a reason at the same time as the other task was canceled by a reason (1)
try:
await handling_task
except asyncio.CancelledError:
print(f"main: CancelledError. Task canceled {handling_task.cancelled()}.")
pass # Task was cancelled correctly
print("main: end")
asyncio.run(main())
所以我的猜测是,它永远不允许抓住一个取消任务的CancelledError?