7

これが機能する理由:

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: 

しかし、これは機能します(違いはStreamReaderw / 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();
    }
}
4

2 に答える 2

14

書き込みを伴う 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();
    }
}
于 2012-01-12T09:55:11.397 に答える
4

例外の完全なスタックトレースを教えてください。私の最初の推測は、まだのメソッドXmlWriter内でストリームにアクセスしようとしている ということです。Dispose()XmlWriter

2番目と4番目のコード例StreamReaderでは、をusingブロックに配置します。これにより、このブロックの最後にあるのDispose()メソッドが呼び出されます。StreamReaderこのメソッドは、リーダーと基になるストリームの両方を閉じます。この後、のDispose()メソッドはXmlWriterストリームにアクセスできなくなります。

更新: stackstraceに基づくと、私は正しかったようです。このDispose()メソッドはを呼び出しますClose()。これは、すでに閉じられているストリームをフラッシュする必要があります。フラッシュするものが何も残っていないはずなので、これはバグのように見えます。

あなたはすでに解決策を与えました:XmlWriterが処分する前にメモリストリームを閉じないでください。

(using-blockは、使用されたオブジェクトを暗黙的に破棄し、StreamReaderまたはをStreamWriter破棄すると、基になるストリームを暗黙的に破棄(および閉じる)することを知っていると思います。)

于 2011-03-30T01:48:31.330 に答える