我创建了一个简单的 webapi .net core 3.1 应用。
我想捕获所有未处理的异常。所以我根据 docs 放置这段代码:
app.UseExceptionHandler(c => c.Run(async context =>
{
var exception = context.Features
.Get<IExceptionHandlerPathFeature>()
.Error;
var response = new { error = exception.Message };
log.LogDebug(exception.Message);
}));
这是我的 Action :
[HttpGet]
public IActionResult Get()
{
throw new Exception("this is a test");
}
当这段代码运行时,我确实看到 UseExceptionHandler
正在工作。
但是当我在操作中的代码是:
[HttpGet]
public IActionResult Get()
{
Task.Run(async () =>
{
await Task.Delay(4000);
throw new Exception("this is a test");
});
return Ok();
}
然后 UseExceptionHandler
NOT 工作。
但是 - 以下代码确实捕获了任务的异常:
AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
{
Debug.WriteLine(eventArgs.Exception.ToString());
};
问题:
- 为什么
UseExceptionHandler
无法识别任务异常? - 如何捕获所有类型的异常?我应该只依赖
AppDomain.CurrentDomain.FirstChanceException
吗?
nb,我确实禁用了 app.UseDeveloperExceptionPage();
最佳答案
回答您的问题。
为什么 UseExceptionHandler 无法识别任务异常?
正如评论中已经建议的那样,您不能使用 UseExceptionHandler
来捕获在非等待任务中启动的异常。 UseExceptionHandler
将您的请求包装在 ASP.NET Core 中间件中。一旦操作向客户端返回 OK
,中间件就不再能够捕获从操作中启动的任务中发生的任何异常。
如何捕获所有类型的异常?我应该只依赖 AppDomain.CurrentDomain.FirstChanceException 吗?
如果您愿意,您可以全局捕获异常并以这种方式记录它们。但我不建议你这样做。您需要实现此事件的唯一原因是您在 Web 请求中启动任务/线程。您无法知道这些任务是否一直在运行(应用程序重启、回收等)。如果您希望使用 ASP.NET Core 启动后台任务,您应该使用 Worker Services,这是执行此操作的预期方式:
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyWorker>();
});
public class MyWorker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
// Do work
}
catch (Exception e)
{
// Log it?
}
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
}
}
}
关于c# - UseExceptionHandler 不会捕获任务异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68242757/