在瞬态生命周期服务中记录即发即弃任务的异常

Logging exception for a fire and forget task in a transient lifetime service

我有一个发射后不管的任务,我需要报告一些遥测数据,任务是否成功并不重要(这就是为什么它是发射后不管的),但我需要确保它是不阻止 api 调用。

当遥测任务中出现异常时,我会记录异常。

我的代码是这样的:

public class MyService : IMyService
{
    private readonly IReporter reporter;
    private static readonly Logger logger = LogManager.GetCurrentClassLogger();

    public MyService (IReporter reporter){

    }
    //..
    public Task<Result> processorRequest()
    {
        // ...
        _ = Task.Run(() =>
        {
            reportTelemetry();
        });

        //...
    }

    private void reportTelemetry()
    {
        try
        {
            reporter.Report();
        }
        catch (Exception ex)
        {
            logger.Warn($"An exception was raised while reporting: {ex.Message}");
        }
    }
}

记录器是在顶部创建的,如下所示:

private static readonly Logger logger = LogManager.GetCurrentClassLogger();

MyServiceReporter 被创建并注入到具有 transient 生命周期的容器中。

我的问题是:

新线程中对 logger 的引用是否会阻止收集 MyService/Reporter?或者 GC 会决定在调用 logger.Warn 之前释放服务吗?

我是否会因为某些原因(应用程序关闭除外)而没有报告异常?

非常感谢任何帮助。

Will the reference to logger in the new thread prevent MyService/Reporter from being collected?

否,但对 this 的引用将确保服务保持活动状态,直到代理启动 运行ning。 lambda 基本上将被重写为

public class MyHiddenDelegate{
    private MyService service;
    public MyHiddenDelegate(MyService service) => this.service = service;
    public void Execute() => service.reportTelemetry();
}

而这个 object 将被执行线程的堆栈或 task-queue 引用。但是 logger 对于任何 object 的生命周期并没有真正发挥任何作用,因为它是一个静态字段。

Or will the GC decide to free the service even before logger.Warn is called?

GC 必须保持 object 活动,直到最后一次使用任何引用。因此,该服务可能在调用 logger.Warn 之前符合 collection 的条件,因为它不需要 this 引用来访问记录器。但这通常没问题,因为 GC 将确保在最后一次使用之前没有收集任何东西。

一个例外可能是您拥有本地资源。然后,您可能需要使用 GC.KeepAlive 来确保在完成本机资源之前终结器不是 运行。

Do I risk not reporting the exceptions for some reason (besides app shutdown)?

据我所知,这不是因为任何 collection 问题。但可能还有其他考虑因素,例如无法捕获的异常。