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

发布于 2024-09-25 21:44:28 字数 3995 浏览 3 评论 0原文

更新于 11/18/2014 - 在浏览 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,每个都有一个属性包,Properties。 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]
private static IDictionary<string, string> threadProperties;

使用 .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 工作。

实际上,我在这里找到了一些有用的帖子,可能有助于讨论:

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

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

提前致谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北城半夏 2024-10-02 21:44:28

警告:这是猜测。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文