.NET MAUI中Serilog捕获未处理异常无法写入Azure Table问题
问题分析与解决
原因
未处理异常触发后,进程会立即终止,而Serilog的Azure Table Storage sink默认采用异步写入机制——此时异步写入操作还未完成,进程就已退出,导致日志无法持久化到Azure Table。而Debug sink是同步输出,所以能在调试窗口看到日志。
解决方案
1. 强制刷新Serilog日志
在未处理异常的处理器中,调用Log.CloseAndFlush()强制将所有待写入的日志同步刷新到Azure Table,确保写入完成后再让进程继续终止。
2. 覆盖MAUI中所有未处理异常场景
MAUI中存在三种常见的未处理异常触发场景,建议全部处理以覆盖所有情况:
AppDomain.CurrentDomain.UnhandledException:处理非UI线程的未处理异常Application.Current.UnhandledException:处理UI线程的未处理异常TaskScheduler.UnobservedTaskException:处理后台Task未被观察到的异常
修改后的代码示例
App.cs 完整代码
public partial class App : Application { private readonly ILogger<App> _logger; public App(ILogger<App> logger) { _logger = logger; InitializeComponent(); // 注册三种异常处理器 AppDomain.CurrentDomain.UnhandledException += HandleAppDomainUnhandledException; Application.Current.UnhandledException += HandleApplicationUnhandledException; TaskScheduler.UnobservedTaskException += HandleUnobservedTaskException; MainPage = new AppShell(); } private void HandleAppDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = (Exception)e.ExceptionObject; _logger.LogCritical(exception, "AppDomain未处理异常"); Log.CloseAndFlush(); } private void HandleApplicationUnhandledException(object sender, Microsoft.Maui.Controls.UnhandledExceptionEventArgs e) { _logger.LogCritical(e.Exception, "UI线程未处理异常"); Log.CloseAndFlush(); e.Handled = true; // 标记为已处理,避免系统默认弹窗 } private void HandleUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { _logger.LogCritical(e.Exception, "后台任务未观察异常"); Log.CloseAndFlush(); e.SetObserved(); // 标记为已观察,避免进程因未处理Task异常终止 } }
优化Program.cs的Serilog配置顺序
将Serilog Logger的初始化放在builder.Logging.AddSerilog()之前,确保DI容器使用已配置好的Logger:
public static class MauiProgram { public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); fonts.AddFont("SF-Pro-Text-Bold.otf", "SFProTextBold"); fonts.AddFont("SF-Pro-Text-Regular.otf", "SFProTextRegular"); fonts.AddFont("materialdesignicons-webfont.ttf", "MaterialDesignIcons"); }); builder.UseMauiApp<App>() .UseMauiCommunityToolkit() .RegisterDataServices() .RegisterViewModels() .RegisterViews(); // 先初始化Serilog Logger var storageConnectionString = "MY_CONNECTION_STRING"; var tableName = "logs"; Log.Logger = new LoggerConfiguration() .WriteTo.AzureTableStorage(connectionString: storageConnectionString, storageTableName: tableName) .WriteTo.Debug() .CreateLogger(); // 再将Serilog添加到MAUI日志系统 builder.Logging.AddSerilog(); return builder.Build(); } }
验证
触发未处理异常后,检查Azure Table Storage,此时异常日志会被正常持久化,同时调试窗口也会输出日志。
内容的提问来源于stack exchange,提问作者adamasan
相关产品推荐
相关产品推荐

