无法从另一个函数取消asyncio.task

问题描述 投票:0回答:1

我本来希望使用

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())

python python-asyncio
1个回答
0
投票

任务由协程

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')
© www.soinside.com 2019 - 2024. All rights reserved.