.NET MAUI全局未处理异常捕获时DisplayAlert引发崩溃
.NET MAUI全局未处理异常捕获修复方案
你遇到的问题核心是AppDomain.CurrentDomain.UnhandledException属于CLR全局异常事件,触发时MAUI的UI上下文可能已经处于不稳定状态,即便调用MainThread.InvokeOnMainThreadAsync,也可能因为应用即将进入终止流程,导致DisplayAlert无法正常渲染甚至引发二次崩溃。
直接用MAUI原生的全局异常处理机制就能解决,以下是完整实现步骤:
1. 替换异常捕获事件
在App.xaml.cs中,移除AppDomain的事件绑定,改用MAUI应用级别的UnhandledException事件,同时补充平台特定的异常捕获(针对Android/iOS的原生异常):
using Microsoft.Maui.Controls; using System; using System.Threading.Tasks; namespace YourAppNamespace { public partial class App : Application { public App() { InitializeComponent(); MainPage = new MainPage(); // MAUI应用级未处理异常捕获 UnhandledException += OnAppUnhandledException; // 补充平台特定异常捕获 RegisterPlatformSpecificExceptionHandlers(); } private async void OnAppUnhandledException(object sender, Microsoft.Maui.Controls.UnhandledExceptionEventArgs e) { e.Handled = true; // 标记异常已处理,避免默认终止流程提前触发 try { // 确保在主线程显示弹窗 await MainThread.InvokeOnMainThreadAsync(async () => { await Current.MainPage.DisplayAlert( "应用错误", $"抱歉,应用发生未预期错误,即将关闭:\n{e.Exception.Message}", "确定" ); }); } catch (Exception ex) { // 极端情况下弹窗失败,记录日志(可选) Console.WriteLine($"弹窗显示失败:{ex.Message}"); } finally { // 弹窗关闭后手动终止应用 Environment.Exit(1); } } private void RegisterPlatformSpecificExceptionHandlers() { #if ANDROID Android.Runtime.AndroidEnvironment.UnhandledExceptionRaiser += (s, e) => { HandlePlatformException(e.Exception); e.Handled = true; }; #elif IOS ObjCRuntime.Runtime.MarshalManagedException += (s, e) => { HandlePlatformException(e.Exception); e.Handled = true; }; #endif } private async void HandlePlatformException(Exception ex) { try { await MainThread.InvokeOnMainThreadAsync(async () => { await Current.MainPage.DisplayAlert( "应用错误", $"抱歉,应用发生未预期错误,即将关闭:\n{ex.Message}", "确定" ); }); } catch { // 忽略弹窗异常 } finally { Environment.Exit(1); } } } }
2. 关键注意点
- 标记
e.Handled = true:告诉MAUI框架该异常已被处理,避免框架默认的终止流程打断弹窗显示。 - 手动终止应用:弹窗关闭后必须调用
Environment.Exit(1),因为未处理异常本质上会导致应用不稳定,继续运行可能引发更多问题。 - 平台特定捕获:Android和iOS有各自的原生异常通道,需要单独处理才能覆盖所有场景。
- 捕获弹窗异常:极端情况下(比如UI上下文完全失效),弹窗可能无法显示,要捕获这类异常避免二次崩溃。
为什么原方案无效?
AppDomain.CurrentDomain.UnhandledException是.NET CLR层面的事件,触发时机早于MAUI的UI生命周期管理,此时MAUI的页面上下文可能已经被销毁,即便切换到主线程,DisplayAlert也无法找到有效的页面载体来渲染弹窗,最终导致应用直接崩溃。而MAUI原生的UnhandledException事件是在UI线程触发的,且绑定到MAUI应用的生命周期内,能保证UI上下文的有效性。
内容的提问来源于stack exchange,提问作者MyselfAndOnlyMe
相关产品推荐
相关产品推荐

