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
仍然试图在XmlWriter
的Dispose()
方法中访问流。
在第二个和第四个代码示例中,将StreamReader
放在一个使用块中。 这会导致在此块结束时调用StreamReader
的Dispose()
方法。 此方法关闭阅读器和基础流。 在此之后, XmlWriter
的Dispose()
方法不再能访问流。
更新:基于stackstrace,我似乎是对的。 Dispose()
方法调用Close()
,而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(); } }