这是一个带有构造函数的日志记录类:
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()
在我看来,基础流已经关闭。
如何抑制(基础流的)关闭或这是另一个问题?
答案 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。