处置 StreamResourceInfo.Stream

发布于 2024-11-10 02:55:23 字数 1138 浏览 0 评论 0原文

我使用 StreamResourceInfo.Stream 从资源中获取 BitmapImage 。使用流后 CloseDispose 是否正确? 我问这个问题是因为在内存分析器中,如果这样做我会收到错误。内存分析器表示已处置的实例尚未进行 GC。

如果我在网上查看,我只能找到 帖子针对此主题。在这篇文章中,回复者说,处理是有意义的。但从当时的情况和效果来看,我认为这是不对的。有人知道什么是正确的行动吗?
附加信息:在我见过的 msdn 示例中,它们不会 Dispose 或 Close。

编辑
感谢 Rick Sladkeys 的回答,我找到了解决方案: 我将 StreamResourceInfo.Stream 分配给 BitmapImage 的 StreamSource 属性。在 msdn 中写道:

如果您希望在创建 BitmapImage 后关闭流,请将 CacheOption 属性设置为 BitmapCacheOption.OnLoad。默认的 OnDemand 缓存选项保留对流的访问,直到需要位图为止,并且清理工作由垃圾收集器处理。

这意味着,BitmapImage 取得流的所有权。这就是为什么如果我手动关闭/处置流,内存分析器会显示错误:位图将保留对流的引用(BitmapCacheOption OnDemand),因此只要 BitmapImage 有效,GC 就不会释放它,但流已经明确处置。在这个具体示例中,处置是一个坏主意。
为了完整起见,我还在 msdn 中查找了调用 TextRange.Load 的上述链接的示例。对于 Load 来说,情况正好相反,Load 不获取所有权,因此流必须在完成后关闭/处置。

I use StreamResourceInfo.Stream to get BitmapImages from resources. Is it correct to Close and Dispose the stream after using it?
I ask because in memory profiler, I get an error if I do so. Memory profiler says that a disposed instance has not been GCed.

If I look on the web, I only can find this post to this topic. In this post, the responding person says, that it is meaninfull to dispose. However if I look at the circumstances and on the effect, I don't think that this is right. Does someone know what is the right action?
Additional information: In the msdn examples I have seen, they don't Dispose or Close.

Edit
Thanks to Rick Sladkeys answer, I found the solution:
I assign StreamResourceInfo.Stream to the StreamSource-property of the BitmapImage. In msdn is written:

Set the CacheOption property to BitmapCacheOption.OnLoad if you wish to close the stream after the BitmapImage is created. The default OnDemand cache option retains access to the stream until the bitmap is needed, and cleanup is handled by the garbage collector.

This means, BitmapImage takes the ownership of the stream. And that's why memory profiler shows an error if I Close/Dispose the stream manually: Bitmap will hold a reference to the stream (BitmapCacheOption OnDemand) and therefore GC will not release it as long as the BitmapImage is valid, but the stream is already explicitely disposed. In this specific example, disposing is a bad idead.
For completness, I have also looked in msdn for the example of the above link where TextRange.Load was called. For Load, it is the opposite, Load does not take the ownership and therefore the stream must be closed/disposed after finishing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

墨落画卷 2024-11-17 02:55:23

这种混乱(我同意确实令人困惑)来自于流的所有权这一微妙但关键的概念。在 MSDN 示例中,您可以将它们视为“看,没有 Dispose,没有 Close,所以我不应该这样做?”

但简单的答案是某人必须负责关闭流。您可能正在调用的 API:

  • Application.GetResourceStream

返回一个 StreamResourceInfo,它是流和 URL 的原始容器。显然 StreamResourceInfo 不拥有该流。因此,当您调用 Application.GetResourceStream 时,现在拥有该 StreamResourceInfo 中包含的流,并且如果您没有对它执行任何其他操作,您将负责关闭它。 Application API 通过将流的所有权作为值返回给我们,将流的所有权从自身转移给我们。

现在,当您将流传递到另一个实体时,令人困惑的部分就出现了。让我们看一个 MSDN 示例:

// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;

在这个示例中,没有 Dispose 也没有 Close。但是,流的所有权转移从我们(调用者)到 XamlReader 实例。溪流不再是我们的责任;我们已将所有权转让给其他人。事实上,XamlReader 在处理完流后确实会调用 Close。一个谜团解开了。

这个问题之所以如此严重,是因为所有权的概念通常隐含在文档中,而我们应该“弄清楚它”。希望只是重新审视所有权的概念以及它是可转让的这一事实,将使您更容易感到调用Close与安全性新主人将会。即使他们不这样做,这也不再是我们的问题了!

The confusion, and I agree it is confusing, comes from the subtle but critical concept of ownership of the stream. In the MSDN examples you can look at them as say "Look, no Dispose, no Close, so I'm not supposed to do that?"

But the simple answer is that somebody has to be responsible for closing the stream. The API you are probably calling:

  • Application.GetResourceStream

returns a StreamResourceInfo that is a primitive container for a stream and an URL. Clearly the StreamResourceInfo does not own the stream. So when you call Application.GetResourceStream you now own the stream that is contained in that StreamResourceInfo and, if you did nothing else with it, you would be responsible for closing it. The Application API transfered ownership of the stream from itself to us by returning it as a value to us.

Now the confusing part comes in when you pass the stream to another entity. Let's take an MSDN example:

// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;

Now in this example there is no Dispose and no Close. But there is a transfer of ownership of the stream from us (the caller) to the XamlReader instance. The stream is no longer our responsibility; we have passed ownership over to someone else. In fact, XamlReader does call Close when it is done with the stream. One mystery solved.

The reason this is so problematic is that the concept of ownership is usually implicit in the documentation and we are supposed to "just figure it out." Hopefully just revisiting th concept of ownership and the fact that it is transferable will make it easier to feel comfortable not calling Close with the security that the new owner will. And even if they don't, it's not our problem anymore!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文