【问题标题】:C# "cached debug log"C#“缓存调试日志”
【发布时间】:2011-08-03 00:12:24
【问题描述】:

我想在这里向 C# 专家寻求建议。我的调试日志有问题。我有一个简单的类,它只打开一个文件,写下提供的字符串并再次关闭文件。但是,有时我需要在使用多线程时使用此调试日志。于是麻烦就来了。我不能多次打开文件,所以我收到一个异常,因为我只是尝试再次打开锁定的文件。为此,我想要一个类似“缓存调试日志”的东西来防止这个异常。有没有简单的方法来实现这个?提前非常感谢。

【问题讨论】:

    标签: c# debugging logging caching


    【解决方案1】:

    C# 4.0 提供了线程安全的集合,例如 System.Collections.Concurrent.ConcurrentQueue<T>。您可以修改您的日志记录类,使其在自己的线程中运行,并且对日志方法的调用只是将消息添加到这样的队列中。这样,您的日志记录线程就可以安全地从队列中读取项目,并在不中断的情况下写入文件。

    编辑

    当然,最方便的做法是开始使用预先存在的日志框架,该框架已经处理了这些内容。我推荐 NLog,尽管 log4net 也是一个值得竞争的竞争者。

    【讨论】:

      【解决方案2】:

      这通常是通过从代码的所有部分调用的单例记录器来完成的;记录器是唯一直接访问文件的东西。已经存在许多框架(nlog、log4net、企业库)可以为您执行此操作。

      【讨论】:

      • 感谢您的回答,我的项目不是很复杂,所以我认为使用 NLog 之类的东西就像使用机关枪杀死苍蝇 :)。
      【解决方案3】:

      您可能想查看 .NET Tracing。我更喜欢只使用内置的 TraceSource 类而不是使用像 nlog 这样的第 3 方日志记录框架。我曾经走在甚至围绕 nlog 写一个外观的道路上,但是有这么多依赖和这么多抽象层,只是为了写一条日志消息似乎很愚蠢。

      您可以在此处查看 TraceSource 的概述:http://msdn.microsoft.com/en-us/library/system.diagnostics.tracesource.aspx

      我们的想法是将追踪与聆听分开。在整个代码中,您可以添加跟踪调用,每个调用都有不同的日志级别(错误、详细、调试)和不同的来源。然后在您的应用程序配置中配置不同的侦听器。

      <system.diagnostics>
          <sources>
            <source name="Source1" switchName="verboseSwitch">
              <listeners>
                <add name="console" />
              </listeners>
            </source>
            <source name="Source2" switchName="warningSwitch">
              <listeners>
                <add name="console" />
              </listeners>
            </source>
          </sources>
          <switches>
            <add name="verboseSwitch" value="Verbose" />
            <add name="warningSwitch" value="Information" />
          </switches>
          <sharedListeners>
            <add name="console" type="System.Diagnostics.ConsoleTraceListener" initializeData="false"/>
          </sharedListeners>
          <trace autoflush="true" indentsize="4">
            <listeners>
              <add name="console" />
            </listeners>
          </trace>
        </system.diagnostics>
      
      
      public void MethodOne()
      {
           TraceSource ts = new TraceSource("Source1");
      
           ts.TraceEvent(TraceEventType.Verbose, 0, "Called MethodOne");
      
           // do something that causes an error
           ts.TraceEvent(TraceEventType.Error, 0, "MethodOne threw an error");
      }
      

      在这里,MethodOne 设置为使用源“Source1”。 Source1 当前在上面配置为收听 Verbose 和更高级别的任何内容。所以这意味着

      Called MethodOne
      MethodOne threw an error 
      

      都将写入控制台

      public void MethodTwo()
      {
           TraceSource ts = new TraceSource("Source2");
      
           ts.TraceEvent(TraceEventType.Verbose, 0, "Called MethodTwo");
      
           // do something that causes a error
           ts.TraceEvent(TraceEventType.Error, 0, "MethodTwo threw an error");
      }
      

      不过,在这里,MethodTwo 被配置为使用 Source2,它只设置为侦听警告及以上。

      所以,当代码运行时,输出将是

      MethodTwo threw an error
      

      这使您可以控制程序不同部分的信息量。也许如果有一天您开始在某个库中看到错误,您可以将该库的跟踪源设置为详细信息,现在可以查看所有调试信息,而不会被来自程序其他部分的数据所淹没。

      我像这样使用不同的侦听器来控制严重错误的流程。我有某些来源和某些错误级别的侦听器,当错误写入日志时,它们会向我发送电子邮件。我不关心 404 错误,但我确实关心注册码中发生的任何事情,例如。

      您有 ConsoleTraceListener 用于写入控制台/调试窗口 FileLogTraceListener 用于写入文件 甚至EventLogTraceListener

      你可以看到内置监听器的完整列表here

      还有第三方监听器,用于发送有关日志事件的电子邮件、存储在数据库中、写入 Azure 表存储等。

      您当然可以使用 NLog 之类的框架来完成所有这些工作。 .NET Trace 方法具有高性能,并且在整个 .NET Framework 中都有使用。恕我直言,选择它不会出错。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多