WPF中如何捕获应用程序崩溃事件?附相关代码咨询
WPF应用崩溃事件捕获的正确实现方式
嘿,我来帮你把WPF里的崩溃捕获代码补全并优化一下~你已经找对了核心的两个捕获点,但还需要完善具体处理逻辑,另外别忘了异步任务里的未捕获异常也要覆盖到!下面是完整的可运行实现:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); // 捕获UI线程上的未处理异常 Dispatcher.UnhandledException += Dispatcher_UnhandledException; // 捕获非UI线程(后台线程)的未处理异常 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // 捕获未被await的异步任务抛出的异常(.NET 4.0+必备) TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; } private void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { // 统一处理异常:写日志、给用户友好提示 HandleException(e.Exception, "UI线程未处理异常"); // 设置为true,告诉WPF我们已经处理了这个异常,应用不会直接崩溃 e.Handled = true; } private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = e.ExceptionObject as Exception; HandleException(exception, "应用域致命未处理异常"); // 注意:这个事件触发的异常大多是致命的,处理完后应用还是会退出 // 这里可以做最后的资源清理,比如关闭文件、释放连接等 } private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { // 处理那些没被await的异步任务抛出的异常 HandleException(e.Exception, "未观察到的异步任务异常"); // 标记异常已被处理,避免GC回收时触发应用崩溃 e.SetObserved(); } private void HandleException(Exception ex, string exceptionType) { if (ex == null) return; // 1. 记录详细错误日志,这里用本地文件示例,你可以换成NLog/Serilog等框架 var logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "WpfAppLogs", "CrashLogs.txt"); Directory.CreateDirectory(Path.GetDirectoryName(logPath)); var errorContent = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} | {exceptionType}\n{ex.ToString()}\n----------------------------------------------------\n"; File.AppendAllText(logPath, errorContent); // 2. 给用户弹出友好提示 MessageBox.Show("抱歉,应用发生了意外错误,我们已经记录了相关信息,应用将退出。", "应用错误", MessageBoxButton.OK, MessageBoxImage.Error); } }
关键知识点说明
- Dispatcher.UnhandledException:专门管UI线程的异常,设置
e.Handled = true可以阻止应用直接崩溃,给你机会处理完日志再优雅退出或者继续运行。 - AppDomain.CurrentDomain.UnhandledException:负责捕获后台线程的未处理异常,这类异常一般是致命的,处理完日志后应用还是会退出,所以重点做最后的资源清理。
- TaskScheduler.UnobservedTaskException:很多新手容易漏掉这个!如果你的异步任务没有用
await,抛出的异常会在GC回收时触发这个事件,不处理的话会直接导致应用崩溃,设置e.SetObserved()就能解决这个问题。
额外注意事项
- 日志路径别写死,用
Environment.SpecialFolder里的目录更稳妥,避免权限问题。 - 如果用了第三方日志框架,直接替换
HandleException里的文件写入逻辑就行,更专业也更灵活。 - 测试的时候可以故意在UI按钮点击事件里抛异常,或者在后台线程里
throw new Exception("测试崩溃"),验证捕获逻辑是否生效。
内容的提问来源于stack exchange,提问作者Dim Mark




