c# using + XmlWriter.Create = “Cannot access a closed Stream.”

断了今生、忘了曾经 提交于 2019-12-07 01:19:55

问题


Why this works:

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

but this does not work ("Cannot access a closed Stream."): Only difference is var dummy = XmlWriter.Create(ms) instead of 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();
        }
    }
}

Stack trace:

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: 

Also this does not work (same error):

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

Stack trace:

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: 

but this works (only difference is 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();
    }
}

回答1:


Can you give us the complete stack trace of the exception? My first guess is that the XmlWriter still tries to access the stream within the Dispose() method of the XmlWriter.

In your second and fourth code example you place the StreamReader in a using-block. This causes the invocation of the Dispose() method of the StreamReader at the end of this block. This method closes both the reader and the underlying stream. After this, the Dispose() method of the XmlWriter can't access the stream anymore.

Update: Based on the stackstrace it seems I was right. The Dispose() method invokes Close(), which in turn wants to flush an already closed stream. This looks like a bug since there should be nothing left to flush.

You already gave the solution: don't close the memorystream before the XmlWriter disposes.

(I assume you know that a using-block implicitly disposes the used object, and that disposing a StreamReader or StreamWriter implicitly disposes (and closes) the underlying stream.)




回答2:


just move reading from MemoryStream block on one level with writing to it.

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


来源:https://stackoverflow.com/questions/5480798/c-sharp-using-xmlwriter-create-cannot-access-a-closed-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!