我本来希望使用
foo_wrapper
函数取消 cancel
,但是,它仍然会生成结果。
如果我将
foo_wrapper
更改为非异步函数并将 self.lock
更改为 threading.Lock
可以解决问题。有什么想法吗?
import asyncio
from typing import List, Optional
class Bar:
def __init__(self):
self.tasks = set()
self.lock = asyncio.Lock()
async def foo(self) -> str:
# Simulate some asynchronous operation
await asyncio.sleep(2)
return "response"
async def foo_wrapper(self) -> str:
task = asyncio.create_task(self.foo())
async with self.lock:
self.tasks.add(task)
return task
def cancel(self):
for task in self.tasks:
print(f'cancel {task}')
print(task.cancel())
async def main():
bar = Bar()
c = bar.foo_wrapper()
bar.cancel()
try:
print(await (await c))
except asyncio.CancelledError:
print('Canceled 2')
if __name__ == "__main__":
asyncio.run(main())
任务由协程
self.tasks
/c
添加到 foo_wrapper
,直到您尝试调用 bar.cancel
之后,协程才会运行。在您调用
bar.cancel()
的时间点,self.tasks
中没有任务。因此,在这种情况下您永远不会取消任务。
访问
self.locks
周围的锁是无关紧要的。 foo_wrapper
可能也不需要异步:
class Bar:
def __init__(self):
self.tasks: set[asyncio.Task] = set()
self.lock = asyncio.Lock()
async def foo(self) -> str:
# Simulate some asynchronous operation
await asyncio.sleep(2)
return "response"
def foo_wrapper(self) -> asyncio.Task:
task = asyncio.create_task(self.foo())
self.tasks.add(task)
return task
def cancel(self):
for task in self.tasks:
print(f'cancel {task}')
print(task.cancel())
async def main():
bar = Bar()
task = bar.foo_wrapper()
bar.cancel()
try:
print(await task)
except asyncio.CancelledError:
print('Canceled 2')