【问题标题】:Log4Net doesn't release resourcesLog4Net 不释放资源
【发布时间】:2013-03-13 10:01:06
【问题描述】:

我有一个 DLL 文件,它将 Log4Net 记录到一个文件中。有一个进程加载 DLL 并可以创建 DLL 的多个实例。

DLL 的每个实例都必须创建一个单独的日志文件。因此,我以编程方式完成所有 Log4Net 配置。

我得到了here.的一些帮助

这是我的代码:

public class LogHelper
{
    private PatternLayout _layout = new PatternLayout();
    private const string LOG_PATTERN = "%date %-5level - %message%newline";
    private String Configuration;

    public static string DefaultPattern
    {
        get { return LOG_PATTERN; }
    }

    public ILog log = null;

    public LogHelper(String configuration)
    {
        Configuration = configuration;

        InitialiseLogger();

        _layout.ConversionPattern = DefaultPattern;
        _layout.ActivateOptions();

        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

        hierarchy.Configured = true;            
        hierarchy.LevelMap.Add(log4net.Core.Level.Debug);
        hierarchy.LevelMap.Add(log4net.Core.Level.Critical);
        hierarchy.LevelMap.Add(log4net.Core.Level.Info);
        hierarchy.LevelMap.Add(log4net.Core.Level.Warn);
        hierarchy.LevelMap.Add(log4net.Core.Level.Error);
        hierarchy.LevelMap.Add(log4net.Core.Level.Fatal);
    }

    ~LogHelper()
    {            
        log.Debug("Closing myself down");
        IAppender[] appenders = log.Logger.Repository.GetAppenders();
        //appenders are empty
        log.Logger.Repository.Shutdown();
    }

    public void InitialiseLogger()
    {            
        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
        Logger newLogger = hierarchy.GetLogger(Configuration) as Logger;

        PatternLayout patternLayout = new PatternLayout();
        patternLayout.ConversionPattern = LOG_PATTERN;
        patternLayout.ActivateOptions();

        RollingFileAppender roller = new RollingFileAppender();            
        roller.Layout = patternLayout;
        roller.AppendToFile = true;
        roller.RollingStyle = RollingFileAppender.RollingMode.Size;
        roller.MaxSizeRollBackups = 4;
        roller.MaximumFileSize = "10MB";
        String name = String.Format("-{0:yyyy-MM-dd_HH-mm-ss}", DateTime.Now);
        roller.File = "C:\\Logs\\" + Configuration + name + ".log";
        roller.ImmediateFlush = true;
        roller.ActivateOptions();

        newLogger.AddAppender(roller);

        log = LogManager.GetLogger(Configuration);
    }

问题是 log.Debug("Closing myself down");未记录到日志文件;我知道它正在被调用。并且日志文件永远不会被释放,除非我停止加载我的 DLL0 的进程,并且我不想停止它。

来自here的链接 解释如何关闭附加程序。但问题是在我的析构函数中调用 log.Logger.Repository.GetAppenders();返回一个空数组。

我该如何解决?

请注意:加载我的 DLL 的进程来自第 3 方,我不知道它的内部结构。

【问题讨论】:

  • DLL 实例是什么意思?
  • 对不起,表达得很糟糕,该进程加载 dll,然后在 dll 中实例化“主类”的多个实例,因此我对该类的每个实例都有一个单独的日志文件。一旦类的实例被销毁,我的文件仍然被主进程锁定。
  • “类的实例被破坏”也表达得很糟糕:) 阅读更多关于 .NET 中的对象生命周期和垃圾收集的内容。这将帮助您更多地了解此过程以及它导致您出现问题的原因。见:stackoverflow.com/questions/12368/how-to-dispose-a-class-in-net/…

标签: c# logging log4net


【解决方案1】:

您正在使用 LogHelper 的析构函数来释放文件

根据the language specification 中的1.6.7.6 析构函数,析构函数将被调用,但您不知道何时。你只知道它会在进程终止之前被调用。

最明显的做法是将析构函数的逻辑移动到将被显式调用的方法(例如Dispose

这样您就可以调用该方法,从而释放文件。

【讨论】:

  • 啊...该死的还有我的 C++ 思维...谢谢您的帮助。
  • 没问题。这就是我们来这里的目的。
【解决方案2】:

所谓的“析构函数”实际上是Finalizer。它们应该只用于释放非托管资源,所以在我看来你正在滥用它。另请注意,Finalizer 很可能在单独的线程上被调用,它可能在有效的随机时间被调用,甚至可能根本不被调用。

您应该让LogHelper 实现IDisposable 并实现Dispose()(它将包含您的终结器中当前的逻辑)。

那么你需要在适当的时候调用Dispose()来管理你的LogHelper的生命周期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2012-01-08
    • 2012-05-04
    • 2012-07-27
    • 2018-11-08
    • 1970-01-01
    相关资源
    最近更新 更多