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 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仍然试图在XmlWriterDispose()方法中访问流。

在第二个和第四个代码示例中,将StreamReader放在一个使用块中。 这会导致在此块结束时调用StreamReaderDispose()方法。 此方法关闭阅读器和基础流。 在此之后, XmlWriterDispose()方法不再能访问流。

更新:基于stackstrace,我似乎是对的。 Dispose()方法调用Close() ,而Close()又想要刷新已经关闭的流。 这看起来像一个bug,因为没有什么可以冲洗。

您已经提供了解决方案:在XmlWriter处理之前不要关闭内存流。

(我假设你知道using-block隐式处理使用过的对象,并且处理StreamReaderStreamWriter隐式地处理(并关闭)底层流。)

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