c#using + XmlWriter.Create =“无法访问已关闭的流。”

为什么这样有效:
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();
    }
}
    
已邀请:
你能告诉我们异常的完整堆栈跟踪吗?我的第一个猜测是
XmlWriter
仍然试图在
XmlWriter
Dispose()
方法中访问流。 在第二个和第四个代码示例中,将
StreamReader
放在一个使用块中。这导致在该块结束时调用
StreamReader
Dispose()
方法。此方法关闭阅读器和基础流。在此之后,
XmlWriter
Dispose()
方法不再能够访问流。 更新: 基于stackstrace看起来我是对的。
Dispose()
方法调用
Close()
,后者又想要刷新已经关闭的流。这看起来像一个bug,因为没有什么可以冲洗。 您已经提供了解决方案:在XmlWriter处理之前不要关闭内存流。 (我假设您知道using-block隐式处理使用过的对象,并且处理
StreamReader
StreamWriter
隐式处理(并关闭)基础流。)     
只需将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();
    }
}
    

要回复问题请先登录注册