丢弃异步任务时,不会显示Nullreference异常

时间:2020-01-27 15:11:36

标签: asynchronous logging .net-core task-parallel-library

我有一个异步任务,其方法签名定义如下:

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

的默认日志记录设置

3 个答案:

答案 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
    }
}