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
相关产品推荐
相关产品推荐

