C#中如何处理MySqlConnector.MySqlException未触发全局未捕获异常问题
问题排查与解决方案
核心原因
你触发异常的代码是异步方法await dbConnection.ExecuteNonQueryAsync(),抛出的异常属于未被观察的异步任务异常,默认不会触发AppDomain.CurrentDomain.UnhandledException事件:
- .NET Framework 4.5 及以上、.NET Core/.NET 5+ 版本中,未被观察的Task异常默认不会导致进程终止,也不会被
AppDomain.UnhandledException捕获 - 只有同步代码抛出的未处理异常才会走你当前配置的全局处理器
排查步骤
- 先检查
ExecuteNonQueryAsync调用链的上层代码,是否存在空catch块悄悄吞掉了MySqlException - 在异步调用处手动加try-catch验证异常可被正常捕获:
try { await dbConnection.ExecuteNonQueryAsync(); } catch (MySqlException ex) { // 确认此处可以捕获到对应的数据库异常 Console.WriteLine($"捕获到SQL异常:{ex}"); throw; }
修复方案
方案1:新增异步全局异常捕获
额外监听TaskScheduler.UnobservedTaskException事件处理未被观察的异步异常:
// 注册异步任务异常处理器 TaskScheduler.UnobservedTaskException += (sender, e) => { _bugsnagClient.Notify(e.Exception); Console.WriteLine(e.Exception); // 标记异常已处理,避免进程强制退出(可根据需求调整) e.SetObserved(); Console.ReadKey(); }; // 若使用.NET Framework 4.5+,还需要在app.config的runtime节点添加以下配置,开启未观察异步异常的进程终止逻辑: // <runtime> // <ThrowUnobservedTaskExceptions enabled="true"/> // </runtime>
方案2:顶层异步逻辑包裹全局try-catch
如果你的控制台入口是异步Main方法,直接在最外层加异常捕获,可覆盖所有同步、异步未处理异常:
static async Task Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionTrapper; try { // 所有业务逻辑的入口 await RunYourBusinessCode(); } catch (Exception ex) { _bugsnagClient.Notify(ex); Console.WriteLine(ex); Console.ReadKey(); Environment.Exit(1); } }
业务异常修复
你当前触发的MySqlException本身是SQL执行错误:profiles表的collection_id字段设置了非空约束且没有默认值,但你的INSERT语句没有给该字段传值,你可以选择:
- 调整INSERT语句,补充
collection_id字段的赋值逻辑 - 修改表结构,给
collection_id设置默认值或者修改为允许为空
内容的提问来源于stack exchange,提问作者user5405648
相关产品推荐
相关产品推荐

