如何解决在瞬态生命周期服务中记录即发即弃任务的异常
我有一个火灾后忘记任务,我需要报告一些遥测数据,不管任务是否成功(这就是为什么它是火灾后忘记),但我需要确保它没有阻塞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();
MyService
和 Reporter
在 transient 生命周期内创建并注入到容器中。
我的问题是:
新线程中对 logger 的引用会阻止 MyService
/Reporter
被收集吗?或者 GC 是否会在调用 logger.Warn
之前决定释放该服务?
我是否会因为某种原因不报告异常(除了应用程序关闭)?
非常感谢任何帮助。
解决方法
新线程中对 logger 的引用是否会阻止 MyService/Reporter 被收集?
否,但对 this
的引用将确保服务保持活动状态,直到委托开始运行。 lambda 基本上将被重写为
public class MyHiddenDelegate{
private MyService service;
public MyHiddenDelegate(MyService service) => this.service = service;
public void Execute() => service.reportTelemetry();
}
并且这个对象会被执行线程的栈或者任务队列引用。但是 logger
并没有真正影响任何对象的生命周期,因为它是一个静态字段。
或者GC会在logger.Warn被调用之前决定释放服务吗?
GC 必须让对象保持活动状态,直到最后一次使用任何引用。因此,该服务在调用 logger.Warn
之前可能符合收集条件,因为它不需要 this
引用来访问记录器。但这通常没问题,因为 GC 将确保在最后一次使用之前没有收集任何东西。
如果您拥有本机资源,则可能是一个例外。然后,您可能需要使用 GC.KeepAlive 来确保在完成本机资源之前不运行终结器。
我是否会因为某种原因不报告异常(除了应用程序关闭)?
据我所知,不是由于任何收集问题。但可能还有其他考虑因素,例如无法捕获的异常。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。