You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:42:36