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

Discord Bot读取配置时意外退出,需等待权限等级变更后执行校验

问题解决思路

一、先排查ReadToEndAsync()导致程序意外退出的问题

程序无报错直接退出,核心原因是异步操作抛出了未捕获异常,被CLR直接终止进程。按以下步骤定位修复:

  • 强制捕获并输出异常:把ReadToEndAsync()调用包裹在try-catch块里,强制打印异常详情,避免异常被吞:
    try
    {
        json = await sr.ReadToEndAsync();
    }
    catch (Exception ex)
    {
        Console.WriteLine($"JSON读取失败: {ex.Message}\n堆栈跟踪: {ex.StackTrace}");
        // 也可以用DSharpPlus的日志系统持久化记录
        discord?.Logger.LogError(ex, "读取JSON流时发生异常");
        // 根据业务需求选择是否抛出,或进行降级处理
        throw;
    }
    
  • 规范StreamReader生命周期:确保sr通过using语句创建,避免流提前被释放导致读取失败:
    using (var sr = new StreamReader(targetStream))
    {
        json = await sr.ReadToEndAsync();
    }
    
  • 修正Bot启动的异步上下文:Main方法必须使用async Task而非void,否则未捕获的异步异常会直接终止程序:
    static async Task Main(string[] args)
    {
        var discord = new DiscordClient(new DiscordConfiguration 
        { 
            Token = "你的Bot令牌",
            TokenType = TokenType.Bot
            // 其他配置项
        });
    
        try
        {
            // 执行你的初始化逻辑(包括JSON读取)
            await discord.RunAsync();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Bot启动失败: {ex.Message}");
        }
    }
    

二、实现等待AccessLvl变更后执行UserAccessControl()的逻辑

放弃低效轮询,推荐用事件驱动或TaskCompletionSource实现精准等待:

方法1:事件驱动(推荐)

给User类添加属性变更事件,当AccessLvl从Awaiting切换为其他值时触发回调:

public class User
{
    private PermissionsLevel.Permslvl _accessLvl;
    // 定义权限变更事件
    public event EventHandler<PermissionsLevel.Permslvl> AccessLevelUpdated;

    public PermissionsLevel.Permslvl AccessLvl
    {
        get => _accessLvl;
        set
        {
            if (_accessLvl != value)
            {
                _accessLvl = value;
                // 触发事件通知订阅者
                AccessLevelUpdated?.Invoke(this, value);
            }
        }
    }
}

在业务逻辑中订阅事件,满足条件后执行权限校验:

// 假设当前用户实例为currentUser
currentUser.AccessLevelUpdated += HandleAccessLevelChange;

private void HandleAccessLevelChange(object sender, PermissionsLevel.Permslvl newLevel)
{
    var user = (User)sender;
    // 注销事件避免重复执行
    user.AccessLevelUpdated -= HandleAccessLevelChange;
    
    if (newLevel != PermissionsLevel.Permslvl.Awaiting)
    {
        UserAccessControl();
        // 如果是异步方法则使用await UserAccessControlAsync();
    }
}

方法2:使用TaskCompletionSource实现异步等待

如果需要以异步等待的方式处理,在User类中维护一个TaskCompletionSource:

public class User
{
    private PermissionsLevel.Permslvl _accessLvl;
    private TaskCompletionSource<PermissionsLevel.Permslvl> _accessLevelTcs;

    public PermissionsLevel.Permslvl AccessLvl
    {
        get => _accessLvl;
        set
        {
            if (_accessLvl != value)
            {
                _accessLvl = value;
                // 当权限脱离Awaiting状态时,完成等待任务
                if (_accessLevelTcs != null && value != PermissionsLevel.Permslvl.Awaiting)
                {
                    _accessLevelTcs.TrySetResult(value);
                    _accessLevelTcs = null;
                }
            }
        }
    }

    // 提供外部调用的等待方法
    public Task<PermissionsLevel.Permslvl> WaitForValidAccessLevel()
    {
        // 如果当前已经不是Awaiting,直接返回结果
        if (AccessLvl != PermissionsLevel.Permslvl.Awaiting)
        {
            return Task.FromResult(AccessLvl);
        }
        _accessLevelTcs = new TaskCompletionSource<PermissionsLevel.Permslvl>();
        return _accessLevelTcs.Task;
    }
}

在业务逻辑中异步等待后执行校验:

// 等待权限等级就绪
await currentUser.WaitForValidAccessLevel();
// 执行权限校验逻辑
UserAccessControl();

内容的提问来源于stack exchange,提问作者Yesalter Yesalt Lastersonal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:42:44