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

Pyrogram多线程环境下超时上下文管理器RuntimeError排查与修复

错误原因

你在Pyrogram的异步主线程里直接调用了aiogram的bot.send_message异步方法,但aiogram的Bot实例绑定的是另一个独立线程的事件循环。跨线程直接调用异步方法会导致事件循环上下文不匹配,触发Timeout context manager should be used inside a task错误——异步方法必须在所属的事件循环上下文中执行,跨线程调用会破坏异步任务的上下文规则。

修复方案

方案1:用线程安全队列解耦消息发送逻辑

在aiogram线程中维护一个线程安全队列,所有发送消息的请求先入队,由aiogram自己的事件循环处理发送:

  1. main.py中初始化队列并启动aiogram线程:
import queue
from threading import Thread
from aiogram import Bot, Dispatcher
import asyncio

# 线程安全队列,用于传递消息请求
message_queue = queue.Queue()

async def aiogram_runner():
    bot = Bot(token="你的aiogram机器人令牌")
    dp = Dispatcher()

    # 后台任务:监听队列并处理消息发送
    async def process_queue():
        while True:
            chat_id, text = await asyncio.to_thread(message_queue.get)
            await bot.send_message(chat_id=chat_id, text=text)
            message_queue.task_done()

    # 启动队列处理任务
    asyncio.create_task(process_queue())

    await dp.start_polling(bot)

def start_aiogram():
    asyncio.run(aiogram_runner())

# 启动aiogram线程
Thread(target=start_aiogram).start()
  1. trade.py中通过队列发送消息:
from main import message_queue

# 替换原bot.send_message调用,改为入队
message_queue.put((目标聊天ID, "要发送的消息内容"))

方案2:用asyncio.run_coroutine_threadsafe跨线程提交任务

直接把aiogram的异步任务提交到它所属的事件循环中执行:

  1. main.py中保存aiogram的事件循环引用:
import asyncio
from threading import Thread
from aiogram import Bot, Dispatcher

aiogram_event_loop = None
aiogram_bot = None

async def aiogram_runner():
    global aiogram_event_loop, aiogram_bot
    aiogram_event_loop = asyncio.get_running_loop()
    aiogram_bot = Bot(token="你的aiogram机器人令牌")
    dp = Dispatcher()
    await dp.start_polling(aiogram_bot)

def start_aiogram():
    asyncio.run(aiogram_runner())

Thread(target=start_aiogram).start()
  1. trade.py中跨线程调用异步方法:
from main import aiogram_event_loop, aiogram_bot
import asyncio

def send_aiogram_msg(chat_id, text):
    # 把异步协程提交到aiogram的事件循环
    coro = aiogram_bot.send_message(chat_id=chat_id, text=text)
    future = asyncio.run_coroutine_threadsafe(coro, aiogram_event_loop)
    # 可选:等待执行结果并处理异常
    try:
        future.result(timeout=10)
    except Exception as e:
        print(f"消息发送失败: {str(e)}")

# 调用示例
send_aiogram_msg(目标聊天ID, "测试消息")
关键注意事项
  • aiogram的Bot实例必须在自己的线程中初始化,不要跨线程直接共享Bot实例,避免上下文冲突。
  • Pyrogram的主线程是异步上下文,所有Pyrogram相关逻辑要在它的事件循环中执行,跨线程调用其他异步框架的方法必须用线程安全的桥接方式(队列或run_coroutine_threadsafe)。

内容的提问来源于stack exchange,提问作者Dude

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:06:33