首页 > 解决方案 > 由于 ILogger是单例,不同线程如何使用 BeginScope() 而不影响其他线程?

问题描述

这与这个问题有关。上下文:.Net Core 3.1,使用Microsoft.Extensions.Logging

记录器是应用程序中的单例IHost。如果我将 (DI) anILogger<T>注入到我的类或方法中,则注入的对象与其他类或方法在请求时收到的实例相同ILogger<T>。这就提出了当我logger.BeginScope($"Processing {transactionId}")在一个线程中使用时会发生什么的问题。其他线程会发生什么?他们是否也更改了日志记录范围?记录范围会混淆吗?如果他们不这样做:这是如何工作的,作为他们的记录器是同一个对象?如果他们确实混合了范围,我怎样才能让两个线程对给定ILogger<T>类型使用不同的日志记录范围?

标签: .net-coredependency-injection

解决方案


这取决于记录器的实现,但通常它们是使用AsyncLocal中保存的一种堆栈来实现的。

调用BeginScope会将新项目放入该堆栈,而相邻的Dispose会将其从该堆栈中弹出。

当通过LogInformation或其他方式调用记录器时,当前堆栈对象的数据将被复制以将其写入控制台或记录器实例配置为执行的任何输出。

AsyncLocal使框架能够跨线程和任务存储信息。

作为参考,请查看Microsoft.Extensions.Logging.Console源代码:


推荐阅读