关闭时,C#FileLogTraceListener抛出异常

时间:2011-10-18 13:38:25

标签: c# dispose destructor finalizer

这是一个带有构造函数的日志记录类:

public QFXLogger(
        int maxFileSize,
        TraceLevel logLevel)
    {
        this.maxFileSize = maxFileSize;
        logSwitch.Level = logLevel;
        //Configure log listener
        traceListener = new FileLogTraceListener();
        traceListener.DiskSpaceExhaustedBehavior = DiskSpaceExhaustedOption.DiscardMessages;
        traceListener.CustomLocation = @".\Log";
        traceListener.BaseFileName = "QFXLog";
        traceListener.AutoFlush = true;
        //Remove all other listeners
        Trace.Listeners.Clear();
        //Add QFX listener
        Trace.Listeners.Add(traceListener);
        //Write header
        WriteSessionHeader();
    }

这是破坏者:

~QFXLogger()
    {
        WriteSessionFooter();
        traceListener.Close();
    }

我只想在记录器获取GC之前向底层流写入页脚。 没有析构函数,一切都很好,但有了它,我得到以下内容:

Unhandled Exception: System.ObjectDisposedException: Cannot access a closed file
.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.Flush(Boolean flushToDisk)
at System.IO.FileStream.Flush()
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Flush()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.ReferencedStream.CloseS
tream()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.CloseCurrentStream()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.Write(String message)
at System.Diagnostics.TraceInternal.Write(String message)
at System.Diagnostics.Trace.Write(String message)
at QFXShell.QFXLogger.WriteSessionFooter()
at QFXShell.QFXLogger.Finalize()

在我看来,基础流已经关闭。

如何抑制(基础流的)关闭或这是另一个问题?

2 个答案:

答案 0 :(得分:2)

c#中的终结符(析构函数)不应该在此方法中使用。终结器仅 以释放非托管资源。调用终结器时,access to other .net objects is not guaranteed并且应该只释放您直接分配的非托管资源。

  

Finalize操作具有以下限制:

     
      
  • 两个对象的终结器不保证以任何特定顺序运行,即使一个对象引用另一个对象。也就是说,如果对象A具有对象B的引用并且两者都具有终结器,则当对象A的终结器开始时,对象B可能已经完成。
  •   

您需要执行的是IDisposable Interface以正确关闭日志文件。可以在Kelly Leahy's IDisposable and Garbage Collection找到一些其他信息。

如果您不处于一次性类有帮助的情况(全局对象等),您可以自己实施Close方法,以确保文件在发布之前有效。

答案 1 :(得分:1)

在析构函数中关闭跟踪器对象为时已晚。在这个时刻,已经可以处理许多不再需要的物体了。

我建议使用公共Dispose方法实现一个IDisposable接口,并在您知道不再需要此QFXLogger对象时立即调用此方法。在这个Dispose方法中,我会检查跟踪器对象是否为NULL,打开然后我会调用Close。它
有关详细信息,请参阅Proper use of the IDisposable interface