我想更详细地了解.Net异常过滤器的工作原理,特别是async
方法和IDisposable
块中的using
个对象。
async
ASP.Net Core请求委托的异常过滤器中有一个GitHub issue关于日志记录范围丢失的问题。范围存储在ConsoleLogScope
中,并且在丢弃一次性物品时丢失。
在以下代码中,演示了两种情况:
第一:
ConsoleLogScope.DisposableScope
已被处理第二
ConsoleLogScope.DisposableScope
已被处理 请注意,仅将lambda标记为async
足以引入第二种行为。 GitHub问题表明它归因于await Task.Delay(100)
,但我和#39;我发现它没有那条线。
这是为什么?它是AsyncTaskMethodBuilder
捕获异常,所以过滤器永远不会被执行吗?
public class Program
{
public static void Main(string[] args)
{
new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureLogging(logging =>
{
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddFilter("Microsoft", LogLevel.Warning);
})
.Configure(app =>
{
var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>();
app.Map("/sync", subApp =>
{
// Exception handler
subApp.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex) when (LogError(logger, ex))
{
}
});
// Logic
subApp.Run((context) =>
{
using (logger.BeginScope("UserId:100"))
{
throw new InvalidOperationException("Something went wrong");
}
});
});
app.Map("/async", subApp =>
{
// Exception handler
subApp.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex) when (LogError(logger, ex))
{
}
});
// Logic
subApp.Run(async (context) =>
{
using (logger.BeginScope("UserId:100"))
{
await Task.Delay(100); // Force TaskAwaiter
throw new InvalidOperationException("Something went wrong");
}
});
});
})
.Build()
.Run();
}
public static bool LogError(ILogger logger, Exception ex)
{
logger.LogError(ex, "Unhandled exception");
return true;
}
}