Release 中出现 ObjectDisposedException 错误,但 Debug 中没有

ObjectDisposedException error in Release, but not in Debug

我正在编写 F# 应用程序并希望在其执行期间记录某些信息。为此,我将控制台输出设置为 .txt 文件。我这样做如下:

type VMwareInterface(serviceUrl:string, userName:string, password:string, baseSnapshotName:string) =  
    let vimClient = new VimClientImpl()
    let vimSession = vimClient.Login(serviceUrl, userName, password)

    // Logging
    let fileStream = new System.IO.FileStream(@"./VMInteractorLog.txt", System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write)
    let streamWriter = new System.IO.StreamWriter(fileStream)
    do System.Console.SetOut(streamWriter)

    [...]

    override x.Finalize () = 
        vimClient.Logout()
        streamWriter.Close()

    [...]

我用以下方式记录内容:

System.Console.WriteLine("ERROR isolating the single VM matching name " + vmName)

当我运行调试应用程序时,一切正常。该文件已正确创建、写入和关闭。不幸的是,当我 运行 发布时,出现以下错误:

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.Dispose(Boolean disposing)
    at System.IO.StreamWriter.Close()

这可能是什么原因造成的?

编辑:

只是想补充一点,该文件已在发布时正确创建,但在出现上述错误之前并未写入。

EDIT2:

我实现了IDisposable接口如下:

let mutable disposed = false

let cleanup (disposing:bool) = 
    if not disposed then
        disposed <- true

    if disposing then
        vimClient.Logout()
        streamWriter.Close()
        fileStream.Close()

interface System.IDisposable with
    member x.Dispose() =
        cleanup(true)
        System.GC.SuppressFinalize(x)

override x.Finalize () = 
    cleanup(false)

这消除了我遇到的错误,但文件仍未写入(在 运行 启用我的 F# 应用程序后文件为空白。

从终结器引用托管对象不是一个好主意,因为 GC 可能已经收集了它们。终结器仅在分配非托管内存(如 IntPtr)时是必需的,并且您希望确保它始终被释放。实现在内部创建一次性对象的类型(如 FileStream)的正确方法是使用 dispose pattern。这使该类型的用户有机会及时释放资源。

总而言之,VMwareInterface 应该使用上面的模式实现 IDisposable。不需要终结器覆盖。

编辑:更正了您的缩进。

let cleanup (disposing:bool) = 
    if not disposed then
        disposed <- true
        if disposing then
            vimClient.Logout()
            streamWriter.Close()
            fileStream.Close()