类构造函数中启动线程创建Asyncio事件循环报错排查
解决"NoneType object has no attribute create_task"错误的思路
核心问题:线程初始化的竞态条件
你的代码在__init__里启动子线程后,立刻在主线程调用t.fun(),这时候子线程可能还没执行到self.loop = asyncio.new_event_loop()这一行,self.loop还是初始的None,自然会触发NoneType错误。线程启动后不会立刻执行目标函数,存在执行顺序的不确定性。
修复步骤
1. 同步线程初始化状态
用threading.Event来等待子线程完成事件循环的初始化,确保调用fun/fun2时self.loop已经被赋值:
import asyncio import threading async def coroutine(): # 补充示例协程实现 await asyncio.sleep(1) print("协程执行完成") class Test(): def __init__(self): self.loop = None self.loop_ready = threading.Event() # 用于同步的事件 self.th = threading.Thread(target=self.create) self.th.start() self.loop_ready.wait() # 等待子线程初始化好loop def __del__(self): if self.loop is not None: self.loop.close() def create(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.loop_ready.set() # 标记loop已初始化完成 self.loop.run_forever() # 让事件循环一直运行,等待任务提交 def fun(self): # 用call_soon_threadsafe线程安全地提交任务 asyncio.run_coroutine_threadsafe(coroutine(), self.loop) def fun2(self): asyncio.run_coroutine_threadsafe(coroutine(), self.loop) t = Test() t.fun() t.fun2() # 可选:添加退出逻辑,等待协程完成后停止loop # asyncio.run_coroutine_threadsafe(shutdown_loop(), t.loop) # t.th.join() async def shutdown_loop(): await asyncio.sleep(2) asyncio.get_running_loop().stop()
2. 其他问题修正
- 你代码中未定义
coroutine协程函数,需要补充具体实现。 - 原代码中用
self.loop.run_until_complete(task)会阻塞调用线程,且在主线程调用子线程的loop的run_until_complete不是合理用法,应该让子线程的loop一直运行,通过asyncio.run_coroutine_threadsafe线程安全地向子线程的事件循环提交任务。 __del__方法中增加对self.loop的非空判断,避免在初始化未完成时触发错误。
关键说明
- 多线程中操作asyncio事件循环必须保证线程安全,
run_coroutine_threadsafe是官方推荐的跨线程提交协程的方式。 - 子线程的事件循环需要通过
run_forever()保持运行,否则提交的任务无法执行。
内容的提问来源于stack exchange,提问作者codegirl2000
相关产品推荐
相关产品推荐

