C# 如何正确处置WebResponse实例?
通常,编写类似这样的代码来使用WebRequest下载一些数据C# 如何正确处置WebResponse实例?,c#,.net,idisposable,webresponse,C#,.net,Idisposable,Webresponse,通常,编写类似这样的代码来使用WebRequest下载一些数据 using(WebResponse resp = request.GetResponse()) // WebRequest request... using(Stream str = resp.GetResponseStream()) ; // do something with the stream str 现在,如果抛出WebException,WebException将引用WebResponse对象,
using(WebResponse resp = request.GetResponse()) // WebRequest request...
using(Stream str = resp.GetResponseStream())
; // do something with the stream str
现在,如果抛出WebException,WebException将引用WebResponse对象,该对象可能调用了Dispose,也可能没有调用Dispose(取决于异常发生的位置,或者响应类的实现方式)——我不知道
我的问题是应该如何处理这个问题。应该是一个非常防御性的编码,并在WebException对象中处理响应(这会有点奇怪,因为WebException不可IDisposable)。还是应该忽略这一点,潜在地访问已处理的对象,或者从不处理IDisposable对象?
MSDN文档中针对WebException.Response给出的示例是完全不充分的。我非常确定,当您有一个using语句时,不管您如何退出using块(无论是通过exception、return还是简单地通过函数前进),对象都会被释放 如果让WebException中的对象离开using块,我怀疑您会发现它已经被释放
记住,处理对象并不一定会阻止以后访问它。稍后尝试调用它的方法可能是不可预测的,这会导致它自身的异常或非常奇怪的行为(因此我不建议这样做)。但是,即使您处理了对象,它的很大一部分仍然留给垃圾收集器,因此仍然可以访问。dispose的目的通常是清理资源句柄(如本例中的活动TCP连接),由于性能原因,在垃圾收集器找到这些句柄之前,您实际上无法将其保留。我提到这一点只是为了澄清,释放它与保留对它的引用的异常并不相互排斥。这是一个非常有趣的问题(尽管值得指出的是,WebResponse对象将在您退出使用时被释放)。我的直觉是,只要您不尝试对这个已处理的WebResponse对象执行任何“操作”操作,那么它是否有一个引用并不重要 您可能仍然可以出于日志记录目的访问实例上的某些属性(如ResponseUri),而无需获得
ObjectDisposedException
,但异常所持有的总体引用不存在,因此您可以继续使用该实例
我很想看看别人怎么说
using (var x = GetObject()) {
statements;
}
(几乎)相当于
var x = GetObject();
try {
statements;
}
finally {
((IDisposable)x).Dispose();
}
因此,您的对象将始终被处置
这意味着在你的情况下
try {
using (WebResponse resp = request.GetResponse()) {
something;
}
}
catch (WebException ex) {
DoSomething(ex.Response);
}
例如,Response将是与本地resp对象相同的对象,当您到达catch处理程序时,本地resp对象将被释放。这意味着DoSomething正在使用已处置的对象,并且可能会因ObjectDisposedException而失败。我已经快速浏览了Reflector,现在可以说:
,作为一个抽象类,将其所有关闭/处理行为委托给其派生类WebResponse
,作为您在这里几乎可以肯定使用的派生类,在其close/dispose方法中,只涉及处理实际的响应流。其余的阶级状态可以留给总司令来决定HttpWebResponse
- 从
块中的try
读取响应流时,请使用WebResponse
块将其括在
中
- 如果您从
块中的catch
读取响应流,请使用WebException
块将其括在
中
- 无需担心如何处理
本身WebException
在游戏结束时,我循环处理它们。
HttpWebRequest
在抛出WebException
之前从底层网络流内部生成一个内存流,因此没有与从WebException.Response
返回的WebResponse
关联的非托管资源
这使得无需对其调用Dispose()
。事实上,试图处理WebException.Response
可能会引起头痛和问题,因为您的代码调用方可能正试图读取与之关联的属性
但是,最好的做法是处置您拥有的任何IDisposable
对象。如果您决定这样做,请确保您没有代码,这取决于您是否能够读取WebException.Response
属性和/或其流。最好的方法是处理异常并抛出新类型的异常,以便在可能的情况下不会向调用方泄漏WebException
也考虑移动到替换<代码> HttpWebRequest < /C> > < /P>
免责声明:不作任何保证。确实如此<代码>使用是try{}finally{}的语法糖,对象将始终在finally块中处理。GetResponse中发生异常如何?结果将不会分配给resp变量,因此从表达式返回,并由using语句处理。我知道一个人可以访问一个已处理的对象,但是,一个人实际上不应该访问。如果这就是这个api的意图,那么这个api不是设计得“糟糕”吗?不,如果GetResponse抛出任何对象,那么将不会处理任何对象。但您无法知道是否已创建了对象,因为只有GetResponse的内部成员才能知道,因此GetResponse有责任确保在这种情况下没有泄漏。作为一个示例,仅说明我的问题WebRequest test=WebRequest.Create(“);尝试使用{(WebResponse resp=test.GetResponse());}