What does DataWriter ObjectDisposedException mean?

2

The following two lines of code execute one right after the other:

this.dataWriter.WriteBytes(message.MessageBuffer);
await this.dataWriter.StoreAsync();

Although the WriteBytes call completes without exception, the StoreAsync call right below it bombs with a ObjectDisposedException and says

The object has been closed. (Exception from HRESULT: 0x80000013)

this.DataWriter (Windows.Storage.Streams.DataWriter) is not null, so what exactly is it saying is "closed?"

EDIT

Just for some further context on how the object is created

this.socket = new StreamSocketListener();
this.socket.ConnectionReceived += this.EventSocketConnectionReceived;
private void EventSocketConnectionReceived(StreamSocketListener sender,
    StreamSocketListenerConnectionReceivedEventArgs args)
{
    if (this.dataWriter == null)
    {
       this.dataWriter = new DataWriter(args.Socket.OutputStream);
    }
}
c#
windows-store-apps
asked on Stack Overflow Jan 4, 2016 by O.O • edited Jan 4, 2016 by O.O

1 Answer

2

I have no experience with Windows.Storage.Streams.DataWriter, but my bet is that you're passing it a stream, then closing it, then calling this. It's probably not the dataWriter that's even throwing the exception, although glancing at the Stack Trace would tell you.

This code would cause this error, and it's a pretty easy mistake to make:

Windows.Storage.Streams.DataWriter dataWriter;
using (var file = File.OpenRead("..."))
{
    dataWriter = new DataWriter(file);
}

dataWriter.WriteBytes(message.MessageBuffer);
await dataWriter.StoreAsync();

Disposal has little to directly do with null. There's rarely much to do with something that's disposed, so we make it null, but that's not necessary.

I'd check around to see what stream you're passing into the constructor, and then look for any references to that stream that might be disposing it (either through a using block like I showed here, or an explicit call to stream.Dispose()).

There are an infinite combination of lines to throw it, and it's unlikely that what you've got is as simple as anything I'm saying here (it's probably spread across constructors and methods, and mixed in with unrelated code). But I'd virtually guarantee that it's something like this pattern.


Just since it sounds like there's some disagreement, the issue here is that it's difficult to tell if something is disposed without telling it to do something.

Because DataWriter is essentially caching up operations, it doesn't talk to the underlying stream until you call StoreAsync(). That's why WriteBytes isn't async, as well. You can imagine an implementation that just pins them onto a List<byte> (although it'd be much more complicated than that, of course).

But when you do call the StoreAsync() method, it reaches out to the stream and says "write this stuff I have cached up." The stream tries, but it's already been closed, so it throws that exception.

That's why it doesn't throw on the first line, but does on the second. And why I'm hazarding the guess that this is a disposed stream, as compared to the DataWriter itself being disposed.


Per your edit and comment, your stream is coming from event args.

My guess is that the stream is getting closed by the event caller, or else the socket is getting closed by the remote client (perhaps due to a timeout?). I don't know whether there's a right way to persist that stream, if it is the former. But that's probably where you should put your research time.

answered on Stack Overflow Jan 4, 2016 by Matthew Haugen • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0