dotnet/wpf · error · ObjectDisposedException

SR.Media_StreamClosed

Error message

SR.Media_StreamClosed

What it means

StreamAsIStream.Verify throws ObjectDisposedException when the wrapped dataStream is null, i.e. the underlying Stream has been closed/disposed after the StreamAsIStream wrapper was created (used by WPF's media layer to expose a managed Stream to unmanaged code). The wrapper remains usable only while its source stream is open.

Solutions

  1. Keep the underlying Stream open for the lifetime of the media object; dispose it only after MediaElement/MediaPlayer is closed
  2. Remove 'using' around streams handed to media APIs and manage lifetime explicitly
  3. Check stream disposal order in async scenarios; ensure playback stopped before disposing

Example fix

// before
using (var fs = File.OpenRead("clip.wmv"))
{
    player.Open(new Uri(fs.Name)); // stream disposed when block exits
}
// after
var fs = File.OpenRead("clip.wmv");
player.Open(new Uri(fs.Name));
player.MediaEnded += (s, e) => fs.Dispose();
Defensive patterns

Strategy: try-catch

Validate before calling

if (stream == null || !stream.CanRead) throw new ObjectDisposedException(nameof(stream));

Type guard

bool IsOpen(Stream s) => s != null && s.CanRead;

Try / catch

try { /* IStream operation */ } catch (ObjectDisposedException ex) { /* recreate stream and re-run media setup */ }

Prevention

When it happens

Trigger: Any IStream-style operation on a StreamAsIStream after its underlying Stream was disposed or closed (e.g. media pipeline still reading a stream the app disposed, or FromSD-created wrapper outliving the source).

Common situations: Disposing a MemoryStream/FileStream that a MediaElement/MediaPlayer is still consuming; closing the stream in a using block while async media playback continues.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/711701bbfc0d5a32. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/StreamAsIStream.cs:501

                canSeek = dataStream.CanSeek;
            }
            catch (Exception e)
            {
                // store the last exception
                _lastException = e;
                return SecurityHelper.GetHRForException(e);
            }

            return NativeMethods.S_OK;
        }
        #endregion

        #region Verify
        private void Verify()
        {
            if (this.dataStream == null)
            {
                throw new System.ObjectDisposedException(SR.Media_StreamClosed);
            }
        }
        #endregion

        #region Delegate Implemetations
        internal static StreamAsIStream FromSD(ref StreamDescriptor sd)
        {
            Debug.Assert(((IntPtr)sd.m_handle) != IntPtr.Zero, "Stream is disposed.");
            System.Runtime.InteropServices.GCHandle handle = (System.Runtime.InteropServices.GCHandle)(sd.m_handle);
            return (StreamAsIStream)(handle.Target);
        }

        internal static int Clone(ref StreamDescriptor pSD, out IntPtr stream)
        {
            return (StreamAsIStream.FromSD(ref pSD)).Clone(out stream);
        }

        internal static int Commit(ref StreamDescriptor pSD, UInt32 grfCommitFlags)

View on GitHub (pinned to 81131a70a4)