C# FileLogTraceListener 关闭时抛出异常

发布于 2024-12-10 13:34:55 字数 1720 浏览 0 评论 0原文

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

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()

在我看来,底层流已经关闭。

我如何抑制(底层流的)关闭或者这是另一个问题?

This is a logging class with a constructor:

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();
    }

And this is the destrcutor:

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

I just want to write a footer to the underlying stream before the logger gets GC.
Without the destructor everything is fine, but with it I get the following:

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()

It seems to me that the underlying stream was already closed.

How can I suppress this closing(of the underlying stream) or is this another issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

跨年 2024-12-17 13:34:55

此方法中不应使用 C# 中的终结器(析构函数)。终结器用于释放非托管资源。调用终结器时,不保证访问其他 .net 对象 并且应该只释放您直接分配的非托管资源。

Finalize 操作具有以下限制:

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

您需要做的是实现 IDisposable Interface 以正确关闭你的日志文件。一些其他信息可以在 Kelly Leahy 的 IDisposable 和垃圾收集中找到

如果您没有遇到一次性类可以提供帮助的情况(全局对象等),您始终可以自己实现一个 Close 方法,以确保文件在发布之前有效。

Finalizers (destructors) in c# should not be used in this method. Finalizers are intended only to release unmanaged resources. When a finalizer is called, access to other .net objects is not guaranteed and should only release unmanaged resources that you directly allocated.

Finalize operations have the following limitations:

  • The finalizers of two objects are not guaranteed to run in any specific order, even if one object refers to the other. That is, if Object A has a reference to Object B and both have finalizers, Object B might have already finalized when the finalizer of Object A starts.

What you need to do is implement the IDisposable Interface to properly close your logging file. Some additional information can be found at Kelly Leahy's IDisposable and Garbage Collection.

If you are not in a situation where a disposable class will help (global object, etc.) you can always implement a Close method yourself to ensure the file is valid before it is released.

云之铃。 2024-12-17 13:34:55

在析构函数中关闭跟踪器对象为时已晚。此时,许多不再需要的对象已经可以被处理掉。

我建议使用公共 Dispose 方法实现 IDisposable 接口,并在您知道不再需要此 QFXLogger 对象时立即调用此方法。在此 Dispose 方法中,我将检查跟踪器对象是否不为 NULL、打开,然后对其调用 Close。

有关更多详细信息,请参阅正确使用 IDisposable 接口

It is too late for you to close the tracer object in the destructor. In this moment a lot of objects which are not needed any more can be already disposed.


I would propose to implement a IDisposable interface with a public Dispose method and to call this method as soon as you know that you are not going to need this QFXLogger object any more. In this Dispose method, I would check if the tracer object is not NULL, open and then I would call Close on it.


See Proper use of the IDisposable interface for more details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文