释放 StreamResourceInfo.Stream

8
我使用 StreamResourceInfo.Stream 从资源中获取 BitmapImage。在使用后关闭和释放流是否正确?我问这个问题是因为在内存分析器中,如果我这样做会出现错误。内存分析器显示已释放的实例未被GC回收。
如果我在网上搜索,只能找到关于此主题的这篇帖子。在这篇帖子中,回答者说,释放是有意义的。但是,如果我看看情况和效果,我不认为这是正确的。有人知道正确的操作吗? 附加信息:在我看过的msdn示例中,他们没有Dispose或Close。
编辑 感谢Rick Sladkeys的答案,我找到了解决方案: 我将StreamResourceInfo.Stream分配给BitmapImageStreamSource属性。在msdn中写道:
将CacheOption属性设置为BitmapCacheOption.OnLoad,如果您希望在创建BitmapImage之后关闭流。默认的OnDemand缓存选项保留对流的访问,直到需要位图,垃圾回收由垃圾回收器处理。
这意味着BitmapImage拥有该流的所有权。这就是为什么内存分析器会显示错误,如果我手动关闭/释放流:位图将持有对流的引用(BitmapCacheOption OnDemand),因此只要BitmapImage有效,GC就不会释放它,但流已经被显式释放。在这个特定的例子中,释放是一个坏主意。 为了完整起见,我还查看了上面链接的示例中调用TextRange.Load的msdn。对于Load,情况相反,Load不拥有所有权,因此必须在完成后关闭/释放流。

流上的Dispose会在内部调用Close。(或者实际上通常是相反的) - Albin Sunnanbo
@Albin:是的,我知道这个。据我所知,在这里Close调用Dispose。但这不是问题所在。问题是,是否需要关闭/处理特定的流。在msdn示例中,他们没有这样做,如果我看一下结果,我怀疑这是预期的。但还是谢谢。 - HCL
1个回答

13
混淆,我同意这很令人困惑,源于“所有权”的微妙但关键的概念。在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;

在此示例中,没有 DisposeClose。 但是存在一个流的所有权转移,从我们(调用方)到 XamlReader 实例。 流不再是我们的责任; 我们已经将所有权转移给了其他人。 事实上,当 XamlReader 完成对流的操作时会调用 Close 方法。 一个谜团得以解开。

这种情况为什么如此棘手,因为文档通常隐含了所有权的概念,而我们应该“自己想出来”。 希望重新审视所有权的概念并且知道它是可转让的,将使我们更容易感到舒适,并且不需要调用 Close 方法,因为我们知道新的所有者会处理它。 即使他们不这样做,这也不再是我们的问题!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接