【问题标题】:What does DataWriter ObjectDisposedException mean?DataWriter ObjectDisposedException 是什么意思?
【发布时间】:2016-01-05 07:48:10
【问题描述】:

以下两行代码依次执行:

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

尽管WriteBytes 调用无一例外地完成,但它正下方的StoreAsync 调用会用ObjectDisposedException 炸弹并说

对象已关闭。 (HRESULT 异常:0x80000013)

this.DataWriter (Windows.Storage.Streams.DataWriter) 不为空,那么“关闭”究竟是什么意思?

编辑

只是为了进一步了解对象是如何创建的

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

【问题讨论】:

  • dataWriter的类型是什么?
  • Windows.Storage.Streams.DataWriter
  • dataWriter 的构造函数在您的代码中是什么样的?你通过什么?
  • 您得到了异常,因为数据写入器是一个已处置的对象。但从发布的代码来看,尚不清楚它是如何发生的。
  • 完全正常。类实现 IDisposable 是因为它们有一个可丢弃的私有成员。并将其留给 那个 类来生成异常。当您调用 WriteBytes() 时,您不太可能使用该一次性对象,因为这只会占用内存。 Store(),当然,现在是 kaboom。添加 ICloseable 很晚才添加到 WinRT 的皱纹,很容易看出为什么现有方法没有额外的检查。

标签: c# windows-store-apps


【解决方案1】:

我没有使用Windows.Storage.Streams.DataWriter 的经验,但我敢打赌,你将它传递给一个流,然后关闭它,然后调用它。可能不是dataWriter 甚至引发了异常,尽管查看堆栈跟踪会告诉你。

这段代码会导致这个错误,而且这是一个很容易犯的错误:

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

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

处置与null 没有直接关系。与已处置的东西几乎没有多大关系,因此我们将其设为 null,但这不是必需的。

我会四处查看您传递给构造函数的流,然后查找对可能正在处理它的流的任何引用(通过像我在这里显示的 using 块,或显式致电stream.Dispose())。

有无数行组合可以抛出它,而且你所得到的不太可能像我在这里所说的那样简单(它可能分布在构造函数和方法中,并与不相关的代码混合在一起)。但我几乎可以保证它就是这种模式。


只是因为听起来有一些分歧,这里的问题是它是difficult to tell if something is disposed 而没有告诉它做某事。

因为DataWriter 本质上是缓存操作,所以在您调用StoreAsync() 之前它不会与底层流对话。这就是为什么WriteBytes 也不是异步的。您可以想象一个将它们固定到 List<byte> 上的实现(当然,它会比这复杂得多)。

但是当您调用StoreAsync() 方法时,它会伸手到流中并说“写这些我已经缓存的东西”。流尝试了,但它已经被关闭了,所以它抛出了那个异常。

这就是为什么它不会在第一行抛出,而是在第二行抛出。以及为什么我冒险猜测这是一个已处置的流,而不是 DataWriter 本身被处置。


根据您的编辑和评论,您的流来自事件参数。

我的猜测是事件调用者正在关闭流,或者远程客户端正在关闭套接字(可能是由于超时?)。我不知道是否有正确的方法来保持该流,如果是前者的话。但这可能是您应该投入研究时间的地方。

【讨论】:

  • @cFrozenDeath WriteBytes 检查底层流的处理吗?我假设不是,在这种情况下,细节是无关紧要的。这就是为什么我跳到我首先说的话,而不是DataWriter本身可以被处置的明显选择。
  • @MatthewHaugen - writer 没有被释放并且它不为空,除非你可以拥有一个不为空但被释放的对象......
  • @O.O 你可以。处置只是意味着 Dispose() 被调用,它可以在任何时候发生,就像任何其他方法一样。您通常希望事后摆脱它,但这不是合同保证。
  • 很好,这个类中使用数据写入器的代码从来没有调用过dispose(并且该成员只在这个类中使用过)。而且我也没有办法检查它是否已被处理。
  • @O.O 是的,我不认为 DataWriter 已被处置。我认为底层流是。您是否查看过传递给构造函数的流,以及在整个代码中对它的哪些引用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-12
  • 2017-06-11
  • 2018-03-05
  • 2023-03-27
  • 1970-01-01
  • 2013-03-09
  • 2020-05-01
相关资源
最近更新 更多