Log4net LogicalThreadContext未按预期工作

时间:2014-04-26 21:31:54

标签: c# asynchronous log4net async-await

我一直在尝试使用Log4nets LogicalThreadContext为每个日志条目提供上下文。我的应用程序非常重视async / await,但是从阅读各种文章开始,LogicalThreadContext应该可以与.NET 4.5以后的异步代码一起正常工作。我使用的是.NET 4.5.1和log4net 2.0.3

我遇到了Stephen Cleary关于日志记录和.NET CallContext的一个很棒的article,结果我决定采用他的代码并使其适应log4net,试图看看是否有什么东西我的代码中可能导致问题的错误。

首先,我完全按原样运行Stephens代码并获得预期的输出

Main 1: <SomeWork>
Main 1 A: <MoreWork>
Main 2: <SomeWork>
Main 2 A: <MoreWork>
Main 1 A: </MoreWork>
Main 1 B: <MoreWork>
Main 2 A: </MoreWork>
Main 2 B: <MoreWork>
Main 2 B: </MoreWork>
Main 2: </SomeWork>
Main 1 B: </MoreWork>
Main 1: </SomeWork>

接下来,我修改了代码以使用log4net而不是Stephens自定义MyStack

internal class Program
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
    private const string StackName = "test";

    private static void Main(string[] args)
    {
        XmlConfigurator.Configure();

        using (LogicalThreadContext.Stacks[StackName].Push("Main"))
        {
            Task.WhenAll(SomeWork("1"), SomeWork("2")).Wait();
        }

        Console.ReadKey();
    }

    private static async Task SomeWork(string stackName)
    {
        using (LogicalThreadContext.Stacks[StackName].Push(stackName))
        {
            Log.Info("<SomeWork>");
            await MoreWork("A");
            await MoreWork("B");
            Log.Info("</SomeWork>");
        }
    }

    private static async Task MoreWork(string stackName)
    {
        using (LogicalThreadContext.Stacks[StackName].Push(stackName))
        {
            Log.Info("<MoreWork>");
            await Task.Delay(10);
            Log.Info("</MoreWork>");
        }
    }
}

我希望得到与以前类似的输出,但这次我得到了以下

Main 1: <SomeWork>
Main 1 A: <MoreWork>
Main 1 A 2: <SomeWork>
Main 1 A 2 A: <MoreWork>
Main 1 A 2 A: </MoreWork>
Main 1 B: <MoreWork>
Main 1 B: </MoreWork>
Main 1 B B: <MoreWork>
Main 1 B B: </MoreWork>
Main 1 B: </MoreWork>
Main 1: </SomeWork>
Main 1: </SomeWork>

请注意,单独的逻辑线程上下文开始重叠。这向我表明log4net并没有正确使用CallContext,但从我能找到的所有内容来看,他们已经解决了这个问题。

有没有其他人遇到过这个或知道为什么会这样?

1 个答案:

答案 0 :(得分:3)

我刚刚在我们的一个项目中遇到过这个问题。这应该解决它:https://github.com/apache/log4net/pull/12

代码基本上遵循@StephenCleary描述的shallow-copy-on-writeimmutable规则,并且附带的测试用例可以承受Task.WhenAll场景。