异常:无法访问已关闭的流(仅限 WinXP!)

Exception: cannot access a closed Stream (WinXP only!)

我正在为我的应用程序尝试 this TFTP 客户端作为客户端。但是,当有时我的程序试图读取流时抛出流已关闭的异常时,某处存在错误。在深入研究源代码后,我发现 TftpTransfer.cs 中有 Dispose 方法,有时会调用该方法然后抛出异常。

我找不到为什么有时会在我使用流之前调用 Dispose 方法(在 TFTP 传输完成后)以及如何解决它。

代码如下,设置position为0时出现异常

        private static AutoResetEvent TransferFinishedEvent = new AutoResetEvent(false);
        ....
        var client = new TftpClient("192.168.0.1");
        var transfer = client.Download("00-02.conf");
        transfer.OnFinished += new TftpEventHandler(transfer_OnFinshed);
        transfer.OnError += new TftpErrorHandler(transfer_OnError);
        Stream stream = new MemoryStream();
        transfer.Start(stream);
        TransferFinishedEvent.WaitOne();
        stream.Position = 0;
        var sr = new StreamReader(stream);
        var myStr = sr.ReadToEnd();
        Console.WriteLine(myStr);
        ...
        static void transfer_OnError(ITftpTransfer transfer, TftpTransferError error)
        {
            Console.WriteLine("Transfer failed: " + error);
            TransferFinishedEvent.Set();
        }

        static void transfer_OnFinshed(ITftpTransfer transfer)
        {
            Console.WriteLine("Transfer succeeded.");
            TransferFinishedEvent.Set();
        }

UPD:尚未奏效的解决方法

        MemoryStream stream = new MemoryStream();
        var sr = new StreamReader(new MemoryStream(stream.GetBuffer()));
        transfer.Start(stream);
        TransferFinishedEvent.WaitOne();
        
        Console.WriteLine(sr.ReadToEnd());

sr 总是指向流的结尾并且它是空的。

UPD2:有一件事可能值得一提。异常无法访问已关闭的流仅发生在 Windows XP 框(我必须坚持使用的 .NET 3.5)上。我试过 Windows 7,尽管有时我看到框架内的流被处置,但我没有例外。同样,在 Windows 上,XP 异常随机发生。大约每 3 次调用我的应用程序就会抛出异常。

流在下载结束时似乎在库中被设计关闭。

//Was that the last block of data?
if (command.Bytes.Length < Context.BlockSize)
{
    Context.RaiseOnFinished();
    Context.SetState(new Closed());
}

Closed 状态只是在 TftpTransfer 的实例上调用 Dispose()(这又关闭了流)。

我认为这可能是库中的一个错误 - 它不拥有流,所以它不应该关闭它,但你现在坚持使用它。

最简单的解决方案是创建一个新的内存流来读取这样捕获的字节::

var sr = new StreamReader(new MemoryStream(stream.GetBuffer());