WebException.Response.GetResponseStream()应该被关闭/释放吗?

8
当我捕获.NET的WebException时,我应该关闭/释放Response.GetResponseStream()吗? MSDN示例没有在异常中关闭或释放任何东西。
许多SO答案建议释放响应和/或流。
我释放了流,这导致了大问题。因为GetResponseStream()(总是?/有时?)返回相同的实例。所以当我获取响应流并释放它,然后可能重新抛出异常到另一层,该层也获取响应流时,它已经被释放并且无法读取,并因此引发更多的异常。

可能是如何正确处理WebResponse实例?的重复问题。 - Deantwo
2个回答

11
简短的回答是,尽管处理您拥有的任何IDisposable对象是一个好的练习,但您不必处理它。
事实上,试图处理WebException.Response或从中返回的流会导致您提到的问题,因为您可能会遇到尝试在上层调用链的异常处理程序中读取其属性的代码。
之所以不处理它是安全的原因是因为HttpWebRequest在抛出WebException之前从网络流中生成了内存流,并且底层网络流已经关闭/处理。 因此,在那一点上,它实际上没有任何未管理的资源。 我假设这是为了更容易处理异常而做出的决定。
不幸的是,MSDN文档没有对此行为进行任何解释。 从技术上讲,实现可能会在将来发生变化,导致您的代码无法处理WebException中获取的HttpWebResponse和/或相关流的问题,但是鉴于许多应用程序依赖于当前行为,这种情况高度不太可能发生改变。
我必须补充一点,即您应该处理您拥有的IDisposable对象。如果可能的话,请使用HttpClient类,这样您就完全不必处理这种情况。如果不能这样做,请考虑自己处理WebException并抛出新类型的异常,该异常不会向代码调用者公开WebException,以便在您处置它后不会遇到调用者试图访问WebException.Response的情况。
免责声明:我为微软工作,但这并不代表我的雇主或.NET Framework团队的观点。没有隐含任何保证。

3

您应该释放此流,因为它可能包含资源。但只有在使用完成后才需要释放它。在不再需要该流之前,停止释放它即可。将流的最后一个用户释放它。

可能应该仅调用GetResponseStream()一次,并明确传递该流,以便清楚地表明它是相同的流。


你能分享一下这个信息的来源吗?你在 MSDN 上看到了什么提示吗?你对“GetResponseStream”有丰富的经验吗?还是只是一般猜测它可能是如何工作的?根据我的经验,猜测在使用这个 API 时通常不会有好结果。 - Peter
如果没有相反的信息,所有可处理的资源都必须被处理。即使它们当前的实现不需要(我并不是说这里的情况是这样),但未来可能会改变。因此,反编译代码不是一个非常可靠的答案。GetResponseStream似乎很可能持有资源。如果你想跳过处理,你必须非常确定。 - usr
1
按照惯例,在.NET中双重释放始终是安全的。释放对象并不会删除它。 - usr
1
没错,但问题不在于双重释放。而是早期释放。这里有一个架构想法:创建一个类来保持IDisposable对象的引用计数。这样你就可以以任意方式传递流,一旦最后一个所有者完成它就会被处理。到目前为止,我从未有过这种需求,但它可能有助于解决你的问题。 - usr
1
这实际上是一个很好的观点。到目前为止,我一直设法构建代码,以便只调用该函数一次。我认为这在任何情况下都是很好的风格。 - usr
显示剩余13条评论

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