2013-03-13 105 views
1

我有一个DLL文件,Log4Net记录到一个文件。有一个过程加载DLL并可以创建该DLL的多个实例。Log4Net不释放资源

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( “合自己失望”);没有记录到日志文件;我知道它被称为。日志文件永远不会被释放,除非我停止加载我的DLL0的进程,并且我不想停止它。

here 的链接解释了如何关闭appender。但问题是,在我的析构函数调用log.Logger.Repository.GetAppenders();返回一个空数组。

我该如何解决?

只是说明:加载我的DLL的过程来自第三方,我不知道它的内部。

+1

你是什么意思的一个DLL的实例? – 2013-03-13 10:02:22

+0

对不起,表达自己很坏,该进程加载dll,然后在dll中实例化一个“主类”的多个实例,所以我有一个单独的日志文件,该类的每个实例。一旦类的实例被销毁,我的文件仍然被主进程锁定。 – Tadzys 2013-03-13 10:07:57

+0

“该类的实例被销毁”也被严重地表达:)在.NET中的对象生命周期和垃圾回收中多读一点。这将帮助你更多地了解这个过程以及它为什么会导致你的问题。请参阅:http://stackoverflow.com/questions/12368/how-to-dispose-a-class-in-net/12394#12394 – 2013-03-13 10:18:57

回答

4

您正在使用LogHelper释放文件(S)

根据the language specification 1.6.7.6析构函数析构函数会被调用析构函数,但你可以不知道什么时候。你只知道它会在进程终止前被调用。

最明显的事情是析构函数的逻辑移动到将被显式调用这样,你就可以调用该方法,从而释放文件的方法(例如Dispose

+0

啊......该死的仍然有我的C++思想..感谢您的帮助。 – Tadzys 2013-03-13 12:03:42

+1

没问题。这就是我们的目标。 – 2013-03-13 14:12:51

2

你称之为“摧毁者”实际上是一个Finalizer。它们只能用于释放非托管资源,所以它在我看来就像是在滥用它。另外请注意,Finalizer可能会在单独的线程中调用,它可能会随机调用,甚至可能根本不会被调用。

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

然后您需要在适当的时间通过拨打Dispose()来管理您的LogHelper的生命周期。