如何取消类内函数启动的指定asyncio任务?取消后任务复现
解决asyncio任务无法取消且自动重启的问题
核心问题定位
你的handle方法末尾调用了asyncio.ensure_future(self.handle()),这会导致当前handle任务执行到结尾时,自动创建一个新的handle任务加入事件循环。哪怕你取消了最初的t1任务,新生成的任务仍会持续运行,造成任务“重启”的假象。
具体解决思路
改掉任务自启动的递归逻辑
将handle改为循环结构,让单个任务持续运行,而非每次生成新任务。示例修改:async def handle(self): while True: # 原[..code...]业务逻辑,比如处理ZMQ消息 msg = await self.sock.recv() # 消息处理逻辑... # 移除asyncio.ensure_future(self.handle())这行代码这样整个
handle是一个持续运行的独立任务,取消它就能彻底停止。用实例属性替代全局变量
t1
全局变量易引发作用域混乱,把任务对象存在ZMQHandler实例中:def start(self): # 移除global t1声明 self.loop.add_signal_handler(signal.SIGINT, self.stop) self.t1 = self.loop.create_task(self.handle()) self.loop.run_forever()停止时直接操作实例属性:
def button_stop_command(): daemon.t1.cancel() # 保留任务检查代码 tasks = asyncio.all_tasks() for task in tasks: print(f'> {task.get_name()}, {task.get_coro()}')正确处理取消异常
任务被取消时会抛出asyncio.CancelledError,需在handle中捕获并做资源清理:async def handle(self): try: while True: # 业务逻辑 msg = await self.sock.recv() # 处理消息 except asyncio.CancelledError: # 清理ZMQ资源 self.sock.close() self.ctx.term() # 重新抛出异常让任务正常结束 raise按需停止事件循环
如果程序无需继续运行,取消任务后可停止事件循环:def button_stop_command(): daemon.t1.cancel() daemon.loop.stop() # 任务检查代码...
内容的提问来源于stack exchange,提问作者stackoverflowforbeginners
相关产品推荐
相关产品推荐

