如何在C#类库项目中用Log4Net捕获所有未处理异常?
在C#类库中捕获所有未处理异常的解决方案
嘿,很高兴你已经搞定了log4net的基础配置,手动日志功能正常运行省了不少事儿!针对你要在C#类库中捕获所有未处理异常(哪怕没写try-catch)的需求,我给你几个实用的方案,根据你的类库运行的宿主场景来选就行:
1. 应用域级别全局捕获
类库总是运行在某个宿主进程的**应用域(AppDomain)**中,注册应用域的UnhandledException事件可以捕获该应用域内几乎所有未被处理的异常,包括后台线程抛出的异常。
你可以在类库中创建一个初始化类,把事件注册逻辑放在里面,让宿主程序在启动时调用这个初始化方法:
using log4net; using System; using System.Threading.Tasks; namespace YourLibraryNamespace { public static class ExceptionHandlerInitializer { private static readonly ILog _logger = LogManager.GetLogger(typeof(ExceptionHandlerInitializer)); public static void SetupGlobalExceptionHandling() { // 捕获应用域内未处理的异常 AppDomain.CurrentDomain.UnhandledException += (sender, args) => { if (args.ExceptionObject is Exception ex) { _logger.Error("【应用域未处理异常】", ex); } else { _logger.Error($"【未知类型未处理异常】: {args.ExceptionObject}"); } }; // 捕获未被观察到的Task异步异常(比如未await的Task抛异常) TaskScheduler.UnobservedTaskException += (sender, args) => { _logger.Error("【未观察到的Task异步异常】", args.Exception); // 标记异常已处理,避免.NET Framework时代的进程终止(.NET Core+默认不会终止,但建议处理) args.SetObserved(); }; } } }
然后让宿主程序调用这个初始化方法:
- 如果是控制台程序:在
Main方法开头调用ExceptionHandlerInitializer.SetupGlobalExceptionHandling(); - 如果是ASP.NET Core项目:在
Program.cs的builder.Build()之前调用 - 如果是WPF/WinForms:在应用启动的入口处(比如
App.xaml.cs的OnStartup方法)调用
2. 针对特定场景的补充处理
如果你的类库会被UI框架(比如WPF/WinForms)作为宿主,还可以建议宿主额外注册UI线程的异常捕获事件(这部分属于宿主层面,但可以作为给用户的提示):
- WPF:注册
Application.Current.DispatcherUnhandledException事件,捕获UI线程未处理异常 - WinForms:注册
Application.ThreadException事件,捕获UI线程未处理异常
关键注意事项
- 类库本身无法强制宿主执行初始化逻辑,所以一定要在文档中明确告知宿主需要调用你的初始化方法,才能启用全局异常捕获
- 确保你的log4net配置中,Error级别的日志输出是开启的(比如配置文件的
<root>节点里设置level value="ERROR",或者对应的logger级别正确) - 测试时可以故意抛出一个未处理异常(比如在类库方法里写
throw new InvalidOperationException("测试未处理异常");),验证log4net是否成功记录日志
内容的提问来源于stack exchange,提问作者ezechiele2517
相关产品推荐
相关产品推荐

