log4net.ThreadContext 和 log4net.LogicalThreadContext 有什么区别? [英] What is the difference between log4net.ThreadContext and log4net.LogicalThreadContext?

查看:27
本文介绍了log4net.ThreadContext 和 log4net.LogicalThreadContext 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 有一个 <一个 href="http://logging.apache.org/log4net/release/sdk/log4net.Util.LogicalThreadContextProperties.html" rel="nofollow noreferrer">LogicalThreadContextProperties 包.

ThreadContext 可能更常被称为MDC".LogicalContext 可能更常被称为LDC".我将在本文的其余部分使用简称.

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

为了比较,NLog 只公开MDC"(现在称为 MappedDiagnosticContext)来存储线程本地属性.NLog的实现使用System.Threading.Thread.SetData,所以它的实现和log4net的一样.

在 log4net 和 NLog 中,MDC"属性存储在字典中,字典本身存储在线程本地存储中.

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

[ThreadStatic]私有静态 IDictionary线程属性;

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

最终,LDC 和 MDC 之间真正、实用的区别是什么?即使阅读了上面链接的 MSDN 主题,我也不清楚.你什么时候会真正使用一个?我看到的关于 log4net 和上下文的绝大多数参考资料/示例似乎都是针对 GDC(全局 - 我理解)、NDC(嵌套 - 我也理解)和 MDC.我在谷歌搜索时可以找到的对 LDC(或 LogicalThreadContext)的大多数参考都与签入 log4net 源代码存储库有关,而不是实际使用.LDC 几乎从不提出问题或示例.

我确实找到了 这个链接提供了一些关于与 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 上找到了一些可能有助于讨论的有用帖子:

使用线程的最佳实践是什么.NET 中的本地存储?

.Net:逻辑线程和线程本地存储?

提前致谢!

解决方案

警告:这是猜测.

假设您正在编写一个服务器,并且为请求提供服务意味着您必须与一系列不同的服务进行通信.作为一名完全现代的开发者,您会异步发出这些请求,并在所有内容得到回复(或超时)时进行协调,以响应原始请求.

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

UPDATED on 11/18/2014 - While browsing the log4net source repository, I found that the implementation of LogicalThreadContext was modified in November 2011 to that it stores its properties using CallContext.LogicalSetData (and gets them using LogicalGetData). This is important because that means that LogicalThreadContext should now work correctly. Any data stored in LogicalThreadContext should be "flowed" to any child threads or tasks. This compares to ThreadContext (and the old implementation of LogicalThreadContext) where data stored in the context would remain local to the current thread and NOT flowed to child threads/tasks.

If you are interested, here is the change:

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

Hopefully someone happening upon this old question will find this information useful.

log4net provides two different "thread context" objects: ThreadContext and LogicalThreadContext, each of which has a property bag, Properties. ThreadContext has a ThreadContextProperties bag while LogicalThreadContext has a LogicalThreadContextProperties bag.

ThreadContext is perhaps more commonly known as "MDC". LogicalContext is perhaps more commonly known as "LDC". I will use the short name for the rest of this post.

MDC.Properties is implemented using System.Threading.Thread.SetData while LDC.Properties is implemented using using System.Runtime.Remoting.Messaging.CallContext.SetData.

For comparison, NLog only exposes "MDC" (now known as MappedDiagnosticContext) to store thread local properties. NLog's implementation uses System.Threading.Thread.SetData, so its implementation is the same as log4net's.

In both log4net and NLog, the "MDC" properties are stored in a dictionary which is itself stored in the thread local storage.

In a case like this, would storing the dictionary in a class member variable decorated with [ThreadStatic] have been equivalent?

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

What be the equivalent (or similar) declaration using .NET 4.0's new ThreadLocal class?

Ultimately, what is the real, practical, difference between LDC and MDC? Even after reading the MSDN topics linked above, it is not clear to me. When would you really use one over the other? It seems like the vast majority of the references/examples that I see for log4net and context is for GDC (global - which I understand), NDC (nested - which I also understand), and MDC. Most of the references that I can find to LDC (or LogicalThreadContext) when googling are related to checkins into the log4net source code repositories, not real-world usage. LDC almost never comes up in questions or examples.

I did find this link that offers some pretty good information about the difference from one of the log4net developers, Nicko Cadell, but it is still not clear to me.

A larger question, not directly related to log4net is what is the practical difference between Thread.SetData and CallContext.SetData?

According to the CallContext MSDN article, CallContext data can be propagated to another AppDomain. To be propagated, a data item stored in the CallContext must expose the ILogicalThreadAffinative interface. So, that seems to be one difference between Thread.SetData and CallContext.

According the Nicko Cadell link, log4net does not implement ILogicalThreadAffinative, so the LDC properties will not be propagated.

Maybe there is enough here that I should be able answer my own question, maybe not. I am still working on understanding.

If you use log4net, do you every use MDC, LDC, both? If you use MDC, is it because most of the "real world" examples seem to use it? If you use LDC, to you have a specific reason for using it? If you use both, how do you choose when to use which?

Note that I have seen some articles regarding MDC (and maybe LDC) maybe not working right in ASP.net applications due to thread switching. I am not particularly interested in this problem as I am not working in ASP.net.

Actually, I have found a couple of useful posts here on SO that might contribute to the discussion:

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

.Net: Logical thread and Thread Local Storage?

Thanks in advance!

解决方案

Warning: this is guesswork.

Suppose you're writing a server, and serving a request means you have to talk to a bunch of different services. Being a thoroughly modern developer, you make these requests asynchronously, coordinating when everything's replied (or timed out) in order to respond to the original request.

That means the work corresponding to a single request is scattered amongst many different threads (processing the web service responses asynchronously). I suspect that CallContext is used to propagate the "everything I'm doing is because of this one incoming request" to different threads, so that you can gather all the logs for that request together. ThreadContext wouldn't help there. Note that I'm assuming all the work is being performed in a single AppDomain, so your concern there wouldn't be a problem.

这篇关于log4net.ThreadContext 和 log4net.LogicalThreadContext 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆