log4net.ThreadContext和log4net.LogicalThreadContext有什么区别?

时间:2010-10-01 16:18:33

标签: .net logging log4net nlog thread-local-storage

2014年11月18日更新 - 在浏览log4net源存储库时,我发现LogicalThreadContext的实现在2011年11月被修改为使用CallContext.LogicalSetData存储其属性(并使用LogicalGetData获取它们)。这很重要,因为这意味着LogicalThreadContext现在应该可以正常工作。存储在LogicalThreadContext中的任何数据都应“流向”任何子线程或任务。这与ThreadContext(以及LogicalThreadContext的旧实现)相比较,其中存储在上下文中的数据将保持在当前线程的本地,而不会流向子线程/任务。

如果您有兴趣,可以参考以下内容:

http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net/Util/LogicalThreadContextProperties.cs?r1=1165341&r2=1207948&diff_format=h

希望有人发现这个老问题会发现这些信息很有用。

log4net提供了两个不同的“线程上下文”对象:ThreadContextLogicalThreadContext,每个对象都有一个属性包。 ThreadContext有一个ThreadContextProperties包,而LogicalThreadContext有一个LogicalThreadContextProperties包。

ThreadContext可能更常被称为“MDC”。 LogicalContext可能更常被称为“LDC”。 我会在这篇文章的其余部分使用短名称。

使用System.Threading.Thread.SetData实现MDC.Properties,而使用System.Runtime.Remoting.Messaging.CallContext.SetData实现LDC.Properties。

为了进行比较,NLog仅公开“MDC”(现在称为MappedDiagnosticContext)来存储线程本地属性。 NLog的实现使用System.Threading.Thread.SetData,因此它的实现与log4net的实现相同。

在log4net和NLog中,“MDC”属性存储在字典中,该字典本身存储在线程本地存储中。

在这种情况下,将字典存储在用[ThreadStatic]修饰的类成员变量中是否已经等效了?

[ThreadStatic]
private static IDictionary<string, string> threadProperties;

使用.NET 4.0的新ThreadLocal类的等效(或类似)声明是什么?

最终,LDC和MDC之间真正的,实际的差异是什么?即使在阅读了上面链接的MSDN主题之后,我也不清楚。你什么时候真的使用一个而不是另一个?似乎我在log4net和上下文中看到的绝大多数引用/示例都是针对GDC(全局 - 我理解),NDC(嵌套 - 我也理解)和MDC。我在google搜索时可以找到LDC(或LogicalThreadContext)的大多数引用都与登录到log4net源代码库有关,而不是真实世界的用法。最不发达国家几乎从未提出问题或例子。

我确实找到了this链接,它提供了一些关于与其中一个log4net开发人员Nicko Cadell的差异的非常好的信息,但我仍然不清楚。

一个更大的问题,与log4net没有直接关系的是Thread.SetData和CallContext.SetData之间的实际区别是什么?

根据CallContext MSDN文章,CallContext数据可以传播到另一个AppDomain。要传播,存储在CallContext中的数据项必须公开ILogicalThreadAffinative接口。所以,这似乎是Thread.SetData和CallContext之间的一个区别。

根据Nicko Cadell链接,log4net没有实现ILogicalThreadAffinative,因此不会传播LDC属性。

也许这里有足够的东西可以回答我自己的问题,也许不是。我仍在努力理解。

如果你使用log4net,你们每个人都使用MDC,LDC吗?如果你使用MDC,是因为大多数“真实世界”的例子似乎都在使用它吗?如果你使用LDC,你有特定的理由使用它吗?如果你同时使用它们,你如何选择何时使用哪个?

请注意,由于线程切换,我看到一些关于MDC(也许是LDC)的文章可能无法在ASP.net应用程序中正常工作。我对这个问题不是特别感兴趣,因为我不在ASP.net工作。

实际上,我在SO上发现了一些可能有助于讨论的有用帖子:

What are best practices for using thread local storage in .NET?

.Net: Logical thread and Thread Local Storage?

提前致谢!

1 个答案:

答案 0 :(得分:8)

警告:这是猜测。

假设您正在编写服务器,并且提供请求意味着您必须与一堆不同的服务进行通信。作为一个完全现代化的开发人员,您可以异步地发出这些请求,协调所有内容的回复(或超时),以便响应原始请求。

这意味着与单个请求相对应的工作分散在许多不同的线程中(异步处理Web服务响应)。我怀疑 CallContext用于将“我正在做的一切都是因为这一个传入请求”传播到不同的线程,以便您可以一起收集该请求的所有日志。 ThreadContext在那里无济于事。请注意,我假设所有工作都在一个AppDomain中执行,因此您的问题不会出现问题。