【问题标题】:c# using + XmlWriter.Create = "Cannot access a closed Stream."c# using + XmlWriter.Create = "Cannot access a closed Stream."
【发布时间】:2011-03-30 01:06:17
【问题描述】:

为什么会这样:

using (var ms = new MemoryStream())
{
    using (var dummy = new StreamWriter(ms))
    {
        var sw = new StreamWriter(ms);
        sw.WriteLine("Hello World");
        sw.Flush();
        using (StreamReader rdr = new StreamReader(ms))
        {
            ms.Position = 0;
            textBoxExc.Text = rdr.ReadToEnd();
        }
    }
}

但这不起作用(“无法访问关闭的流。”): 唯一的区别是var dummy = XmlWriter.Create(ms) 而不是var dummy = new StreamWriter(ms)

using (var ms = new MemoryStream())
{
    using (var dummy = XmlWriter.Create(ms))
    {
        var sw = new StreamWriter(ms);
        sw.WriteLine("Hello World");
        sw.Flush();
        using (StreamReader rdr = new StreamReader(ms))
        {
            ms.Position = 0;
            textBoxExc.Text = rdr.ReadToEnd();
        }
    }
}

堆栈跟踪:

System.ObjectDisposedException was unhandled by user code
  Message=Cannot access a closed Stream.
  ObjectName=""
  StackTrace:
       w System.IO.__Error.StreamIsClosed()
       w System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
       w System.Xml.XmlUtf8RawTextWriter.FlushBuffer()
       w System.Xml.XmlUtf8RawTextWriter.Flush()
       w System.Xml.XmlWellFormedWriter.Close()
       w System.Xml.XmlWriter.Dispose(Boolean disposing)
       w System.Xml.XmlWriter.Dispose()
       w SerializeTest.MainPage.buttonExc_Click(Object sender, RoutedEventArgs e)
       w System.Windows.Controls.Primitives.ButtonBase.OnClick()
       w System.Windows.Controls.Button.OnClick()
       w System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
       w System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
       w MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)
  InnerException: 

这也不起作用(同样的错误):

using (var ms = new MemoryStream())
{
     using (var writer = XmlWriter.Create(ms))
    {
        var serializer = new DataContractSerializer(typeof(T));
        serializer.WriteObject(writer, objectToSave);
        writer.Flush();
        ms.Position = 0;
        using (StreamReader rdr = new StreamReader(ms))
        {
            return rdr.ReadToEnd();
        }
    }
}

堆栈跟踪:

System.ObjectDisposedException was unhandled by user code
  Message=Cannot access a closed Stream.
  ObjectName=""
  StackTrace:
       w System.IO.__Error.StreamIsClosed()
       w System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
       w System.Xml.XmlUtf8RawTextWriter.FlushBuffer()
       w System.Xml.XmlUtf8RawTextWriter.Flush()
       w System.Xml.XmlWellFormedWriter.Close()
       w System.Xml.XmlWriter.Dispose(Boolean disposing)
       w System.Xml.XmlWriter.Dispose()
       w SerializeTest.SerializeToStringTest[T](T objectToSave)
       w SerializeTest.MainPage.button2A_Click(Object sender, RoutedEventArgs e)
       w System.Windows.Controls.Primitives.ButtonBase.OnClick()
       w System.Windows.Controls.Button.OnClick()
       w System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
       w System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e)
       w MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName)
  InnerException: 

但这有效(唯一的区别是StreamReader w/o using):

using (var ms = new MemoryStream())
{
     using (var writer = XmlWriter.Create(ms))
    {
        var serializer = new DataContractSerializer(typeof(T));
        serializer.WriteObject(writer, objectToSave);
        writer.Flush();
        ms.Position = 0;
        StreamReader rdr = new StreamReader(ms);
        return rdr.ReadToEnd();
    }
}

【问题讨论】:

  • Silverlight 4 上没有重现,我没想到会有。
  • 您找到了升级的好理由。

标签: c# silverlight using xmlwriter


【解决方案1】:

只需将 MemoryStream 块的读取移动到一个级别并写入它。

using (var ms = new MemoryStream())
{
     using (var writer = XmlWriter.Create(ms))
    {
        var serializer = new DataContractSerializer(typeof(T));
        serializer.WriteObject(writer, objectToSave);
        writer.Flush();
        ms.Position = 0;        
    }
    using (StreamReader rdr = new StreamReader(ms))
    {
        return rdr.ReadToEnd();
    }
}

【讨论】:

  • 完美,尝试将 XmlSchema 转换为字符串时遇到了同样的问题。一旦我按照此处所示移动了该块,一切都很好。
  • 也为 .net core 工作过
【解决方案2】:

您能给我们提供异常的完整堆栈跟踪吗?我的第一个猜测是XmlWriter 仍然尝试在XmlWriterDispose() 方法中访问流。

在您的第二个和第四个代码示例中,您将 StreamReader 放在 using 块中。这会导致在此块末尾调用StreamReaderDispose() 方法。此方法关闭阅读器和底层流。之后,XmlWriterDispose() 方法就不能再访问流了。

更新: 根据stackstrace,看来我是对的。 Dispose() 方法调用Close(),后者又想要刷新已经关闭的流。这看起来像一个错误,因为应该没有任何东西可以刷新。

您已经给出了解决方案:在 XmlWriter 释放之前不要关闭内存流。

(我假设您知道 using-block 隐式处置使用的对象,处置 StreamReaderStreamWriter 隐式处置(并关闭)底层流。)

【讨论】:

    猜你喜欢
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 2021-12-29
    • 2020-11-16
    • 1970-01-01
    • 2022-11-09
    相关资源
    最近更新 更多