【问题标题】:log4net: How to distinguish between different forms on the same UI thread?log4net:如何区分同一 UI 线程上的不同表单?
【发布时间】:2015-09-02 17:54:22
【问题描述】:

有没有办法(NDC、Properties、...?)在所有 log4net 消息中包含每个表单的名称/ID,以便我可以区分所有日志消息中的表单?

我的所有表单中都使用了许多服务方法等,我想看看例如服务被调用是由于用户以什么形式输入的结果(想想多个非模态相似的形式(同一个类),在同一个 UI 线程中运行,包含一个按钮,并且在按钮的 Click-Event 中,调用了一个服务方法。在服务方法内部,有日志调用。在日志消息中,我希望有一个属性,其中包含按钮被单击的确切表单实例的信息)。

我不想修改所有日志记录调用。网络上的日志上下文/NDC 的示例都只讨论了多个客户端/asp.net 请求等,而不是 1 个线程中的多个表单。

谢谢, 蒂姆

【问题讨论】:

  • 边想:一种可能的解决方法是将每个表单放在自己的单元线程中,并通过线程名称区分日志事件。但是我需要同步/“线程安全”所有表单间事件,对吗?这可能是一个维护 PITA……有人有更好的主意吗?

标签: forms events properties log4net non-modal


【解决方案1】:

为此,请将表单的 Activated 事件中的属性设置为您要记录的内容:

private void Form1_Activated(object sender, System.EventArgs e)
{
    // for example
    log4net.GlobalContext.Properties["Name"] = this.GetType().Name;
    log4net.GlobalContext.Properties["Id"] = this.Id;
}

在你的日志配置中,你可以为每个 appender 引用 PatternLayout 中的属性:

<layout type="log4net.Layout.PatternLayout">
  <conversionPattern value="%property{Name} : %property{Id} : [%level]- %message%newline" />
</layout>

编辑:要保留多个值,请使用堆栈,如本单元测试中的输出:

现在在 TestClass1 现在在 TestClass2

using log4net.Appender;
using log4net.Config;
using log4net.Core;
using log4net.Layout;
using NUnit.Framework;

namespace log4net.Tests
{
    [TestFixture] // A NUnit test
    public class log4net_Stacks
    {
        [SetUp]
        public void Setup()
        {
            ConsoleAppender ca = new ConsoleAppender
            {
                Layout = new PatternLayout("%property{demo}"),
                Threshold = Level.All
            };

            ca.ActivateOptions();
            BasicConfigurator.Configure(ca);
        }

        [Test]
        public void Stacks_Demo()
        {
            new TestClass1().Method1();
            LogManager.GetLogger("logger").Debug("");
            ThreadContext.Stacks["demo"].Clear();
        }

        private abstract class BaseTestClass
        {
            protected static void AddToStack(string message)
            {
                ThreadContext.Stacks["demo"].Push(message);
            }
        }

        private class TestClass1 : BaseTestClass
        {
            public void Method1()
            {
                AddToStack("Now in " + GetType().Name);
                var tc2 = new TestClass2();
                tc2.Method2();
            }
        }

        private class TestClass2 : BaseTestClass
        {
            public void Method2()
            {
                AddToStack("Now in " + GetType().Name);
            }
        }    
    }
}

【讨论】:

  • thx,是的,这解决了直接问题,但我也有一些情况,其中一种形式的 GUI 事件以几种形式(例如,在事件源形式和一个其他形式)。在这种情况下,我仍然看不到以什么形式发生了什么。是否有可能在那些更复杂的情况下进行区分?
  • @Dr.TimdosSantos 在这种情况下,您可能会使用ThreadContext class's Stacks property
  • 您能否详细说明如何利用 ThreadContext.Stacks 属性来执行此操作,而不必在每个 UI 事件处理程序中调用 using (ThreadContext.Stacks["Foo"].Push("Blah")) {...}
  • @Dr.TimdosSantos 编辑答案以在堆栈上显示多个值 - 您必须在使用后清除这些值。
  • 谢谢,我会调查一下
猜你喜欢
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多