我有一个异步任务,其方法签名定义如下:
public async Task<bool> HandleFooAsync()
以异步方式执行此任务并丢弃结果时,此任务中发生的异常不会显示在我们的日志中。
_ = _slackResponseService.HandleFooAsync();
当我等待任务执行时,我在日志中看到错误
var result = await _slackResponseService.HandleFooAsync();
这是预期的行为吗?有没有一种方法可以在这两者之间实现解决方案:“不要等待结果,但是仍然记录错误。”我们花了数小时调试日志记录设置,只是为了了解我们的日志记录设置是正确的,但是discard
在dotnet中意味着所有内容都被丢弃-甚至是日志。从Python背景出发,这对我们来说是一个全新的视角。
我们的日志记录设置遵循dotnet core 3 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1
的默认日志记录设置答案 0 :(得分:3)
是的,这是预期的行为。以这种方式进行的调用可被视为反模式。您可以阅读有关内容C# Async Antipatterns
您需要一种称为“失火”的东西。可以在仓库AsyncAwaitBestPractices中找到它的一种实现方式(也有可用的Nutt)。
答案 1 :(得分:0)
.net和netcore中的任务需要等待。如果不等待,则可能会在异步方法完成之前破坏作用域。
如果您想在后台运行任务而不希望等待结果,则可以在.netcore中使用BackgroundService或第三方(例如Hangfire)来支持开火并忘记工作
https://medium.com/@daniel.sagita/backgroundservice-for-a-long-running-work-3debe8f8d25b https://www.hangfire.io/
答案 2 :(得分:0)
一种解决方案是订阅TaskScheduler.UnobservedTaskException
事件。这是不理想的,因为该事件是在有故障的Task
被垃圾回收时引发的,这可能在实际故障后很长时间发生。
另一种解决方案是每次触发并忘记任务时都使用扩展方法。像这样:
_slackResponseService.HandleFooAsync().FireAndForget();
这是FireAndForget
方法的基本实现:
public async static void FireAndForget(this Task task)
{
try
{
await task;
}
catch (Exception ex)
{
// log the exception here
}
}