You need to enable JavaScript to run this app. 非rewrite版discord.py如何创建可并行运行的多循环后台任务?
优惠活动
大模型
产品
解决方案
定价
更多

非rewrite版discord.py如何创建可并行运行的多循环后台任务?

核心问题定位

当前代码的阻塞根源来自start_tasks方法的任务创建逻辑错误:

  • 你在列表推导式中对self.client.loop.create_task()的返回结果执行了await操作
  • 对于非rewrite版本的discord.py配套的asyncio版本,loop.create_task是同步方法:它会将传入的协程封装为可调度的Future并立刻返回,本身不需要被await;如果你对返回的Future直接await,代码逻辑会停在这一步,直到当前对应的任务完全执行结束,才会进入下一个任务的创建流程
  • 结合task_1内置的60分钟asyncio.sleep长阻塞,后续的task_2、task_3根本没有被创建的机会,最终表现为只有第一个启动的任务在运行,其余任务全部被阻塞
可并行运行的修正实现
import asyncio
import discord

class BackgroundTasksCollection:
    def __init__(self, client: discord.Client):
        self.client = client
        # 存储已启动的任务句柄,避免on_ready重复触发导致任务堆叠
        self.running_tasks = set()

    async def start_tasks(self):
        # 已存在运行中的任务时直接退出,防止重复创建
        if self.running_tasks:
            return
        for name in dir(self):
            if name.startswith("task_"):
                task_coro = getattr(self, name)()
                # 同步创建任务,不等待任务执行完成,让事件循环自动调度所有任务并行运行
                task_handle = self.client.loop.create_task(task_coro)
                self.running_tasks.add(task_handle)
                # 增加回调,将已结束的任务从集合中移除,避免内存泄漏
                task_handle.add_done_callback(self.running_tasks.discard)

    # 以下原有任务逻辑无需修改
    async def task_1(self):
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(60 * 60)
            # 原有业务逻辑

    async def task_2(self):
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(1)
            # 原有业务逻辑

    async def task_3(self):
        await self.client.wait_until_ready()
        while not self.client.is_closed():
            await asyncio.sleep(30)
            # 原有业务逻辑


class MyClient(discord.Client):
    def __init__(self, **options):
        super().__init__(**options)
        self.tasks = BackgroundTasksCollection(self)

    async def on_ready(self):
        await self.tasks.start_tasks()
        # 原有on_ready逻辑
常见坑点提醒
  • 所有任务内的等待逻辑统一使用asyncio.sleep,严禁使用同步的time.sleep,同步阻塞会卡住整个事件循环,导致所有机器人交互、后台任务全部停摆
  • 每个任务内部建议增加基础异常捕获,避免单个任务抛出未捕获的异常被事件循环静默吞掉,提升排查效率
  • 不需要额外使用线程来实现后台并行,asyncio的单线程事件循环本身就能调度大量协程并行轮转运行,配合非阻塞的sleep逻辑即可实现所有任务同时正常运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 04:06:05