You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步事件循环被阻塞的原因及解锁方案(要求仅修改sender方法)

异步事件循环被阻塞的原因及解锁方案(要求仅修改sender方法)

我来帮你拆解问题根源,再给出符合要求的解决方案:

问题出在哪?

你的代码里藏了一个容易忽略的细节:Drone类初始化时,self.base_loop = asyncio.get_event_loop()获取的是默认事件循环,但在main函数里,你后来又创建了一个全新的事件循环loop = asyncio.new_event_loop(),还把它设为了main线程的当前循环。这就导致你存在Drone里的base_loop和实际运行run协程的循环根本不是同一个!

所以当你在sender线程用asyncio.run_coroutine_threadsafe(self.adjust_yaw(), self.base_loop)提交协程时,这个任务被送到了一个没有在运行的旧循环上,自然不会被执行。而run协程里的await asyncio.sleep(.2)其实并没有阻塞事件循环——它会主动让出控制权,只是你提交的任务没到正确的循环上而已。

仅修改sender方法的解决方案

如果你不想改动代码的其他部分,只修改sender方法的话,可以直接用asyncio.run来运行adjust_yaw协程。asyncio.run会自动创建一个临时事件循环来执行这个协程,虽然和运行run的循环不是同一个,但能保证adjust_yaw正常执行:

def sender(self):
    time.sleep(2)
    print("adjusting yaw angle...")
    asyncio.run(self.adjust_yaw())

运行修改后的代码,你就能看到Yaw angle adjusted.的输出了。

更规范的可选方案(需少量修改其他部分)

如果希望adjust_yaw和run在同一个事件循环里运行(比如需要共享状态、协作执行),那最优解是让Drone的base_loop指向实际运行的循环。只需要在main函数里创建新循环后,把它赋值给drone的base_loop:

if __name__ == '__main__':
    
    drone = Drone()
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    # 新增:让drone的base_loop指向实际运行的循环
    drone.base_loop = loop
    
    th = threading.Thread(target=drone.sender, name="MissionRunner", args=[])
    th.start()
    
    loop.run_until_complete(drone.run())

这样原来的sender方法不用改,提交的协程就会被正确送到运行run的循环上执行。

验证结果

不管用哪种方案,运行代码后都会看到如下输出:

Mission was temporarily halted, starting waiting loop...
adjusting yaw angle...
Yaw angle adjusted.

备注:内容来源于stack exchange,提问作者user3792852

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:57:59