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

Discord.py斜杠命令如何用线程处理耗时任务并返回结果?

解决Discord.py耗时斜杠命令的线程与后续消息发送问题

核心问题原因

直接将interaction对象传入线程后,父协程结束时会回收该对象的上下文资源(如HTTP会话绑定、事件循环关联),导致后续调用interaction.followup.send时因对象失效而失败。同时线程内无法直接调用异步方法,必须通过事件调度处理。


推荐解决方案:使用asyncio.to_thread(无需手动管理线程)

这个方法能将同步耗时函数放到线程池执行,既不阻塞机器人的事件循环,又能保持interaction对象的上下文有效性,代码简洁易维护。

修改后的完整代码:

import asyncio

# 你的耗时同步函数
def clientFunction(things: str) -> str:
    # 模拟5分钟耗时操作
    import time
    time.sleep(300)
    return f"处理完成:{things}"

# TEST COMMAND
@bot.tree.command(name="test_command", description="Just a test")
@app_commands.describe(things = "nice parameter")
async def userTestEvent(interaction: discord.Interaction, things: str):
    await interaction.response.defer()
    # 将耗时函数提交到线程池执行,不阻塞事件循环
    result = await asyncio.to_thread(clientFunction, things)
    # 正常发送后续结果消息
    await interaction.followup.send(f"{interaction.user.mention}, {result}")

备选方案:手动线程+交互Token发送消息

如果必须手动管理线程,不要传递整个interaction对象,而是提取关键信息(交互Token、用户ID),通过Webhook接口发送后续消息,脱离原对象的上下文依赖。

代码示例:

import threading
import asyncio
from discord import Webhook, AsyncWebhookAdapter

# 你的耗时同步函数
def clientFunction(things: str) -> str:
    import time
    time.sleep(300)
    return f"处理完成:{things}"

def run_task(things: str, followup_token: str, user_id: int, bot):
    # 执行耗时任务
    result = clientFunction(things)
    # 将发送消息的异步任务提交到机器人的事件循环
    asyncio.run_coroutine_threadsafe(
        send_followup(bot, followup_token, user_id, result),
        bot.loop
    )

async def send_followup(bot, token: str, user_id: int, result: str):
    # 通过交互Token创建独立Webhook
    webhook_url = f"https://discord.com/api/webhooks/{bot.application_id}/{token}"
    async with AsyncWebhookAdapter(bot.session) as adapter:
        webhook = Webhook.from_url(webhook_url, adapter=adapter)
        user = bot.get_user(user_id)
        await webhook.send(f"{user.mention}, {result}")

# TEST COMMAND
@bot.tree.command(name="test_command", description="Just a test")
@app_commands.describe(things = "nice parameter")
async def userTestEvent(interaction: discord.Interaction, things: str):
    await interaction.response.defer()
    # 启动线程,传递必要参数而非整个interaction对象
    thread = threading.Thread(
        target=run_task,
        args=(things, interaction.followup.token, interaction.user.id, bot)
    )
    thread.start()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:07:27