关闭HttpWebRequest以释放资源

3

我正在用C#创建HTTP WebRequests来浏览一个网站。我创建请求,获取响应并将其读入StreamReader。然后我使用相同的请求变量创建新请求并获得新响应...

以下是我的代码:

HttpWebRequest request;
WebResponse response;
Stream responseStream;
StreamReader reader;
string responseFromServer;

request = (HttpWebRequest)WebRequest.Create("https://www.firstRequest.com");

//set cookies and headers here... 

response = request.GetResponse();

responseStream = response.GetResponseStream();
reader = new StreamReader(responseStream);
responseFromServer = reader.ReadToEnd();


//second request using the same variables
request = (HttpWebRequest)WebRequest.Create("https://www.secondRequest.com");
response = request.GetResponse();

responseStream = response.GetResponseStream();
reader = new StreamReader(responseStream);
responseFromServer = reader.ReadToEnd();

我知道我必须关闭响应,流和流阅读器以释放资源。我是不是需要在每个请求之间这样做,还是只需要在一切结束时这样做?
2个回答

3

是的,每次都需要清理自己的代码。只需利用你忽略的IDisposable功能:

因此,你可以

using(response = request.GetResponse())
{
    using(responseStream = response.GetResponseStream())
    {
        using(reader = new StreamReader(responseStream))
        {
            responseFromServer = reader.ReadToEnd();
        }
    }
}

更简洁地说:
using(response = request.GetResponse())
using(responseStream = response.GetResponseStream())
using(reader = new StreamReader(responseStream))
{
    responseFromServer = reader.ReadToEnd();
}

现在你不需要担心调用Close了。IDisposable实现会在using块结束时为您处理它。


那么,我应该在哪里放置需要放置在您的using语句之间的代码呢? - Diane2
当然。你使用了using、using、using,然后是你的代码块。我能在代码块中引用响应吗,还是它已经关闭了?我不理解你编写代码的方式。谢谢。 - Diane2
所以我改动了我的代码,希望它更加自说明。是的,在其使用块内可以引用响应。块结束后,“Dispose”将自动调用“已使用”的项。调用Dispose和Close是等效的,因此这满足您的要求。一旦调用Dispose,继续使用已释放的项通常是不安全的。但将新响应分配给变量是安全的。 - spender

2
尽管@spender在说你应该使用using指令时有一定道理,但我认为他的答案并没有回答你的问题或特别有帮助。
当考虑这样的问题时,请考虑C#的基础知识和实现IDisposable的对象。实现IDisposable的类使用未受管理的资源,在不再使用该类时需要释放这些资源。这发生在using块的结尾或调用Dispose时。
然而,在调用Dispose后,对象就不应再使用了。这与Close有根本的区别。使用Close响应会释放资源,并且可以将同一对象重新用于另一个请求。 MSDN for Close 现在让我们考虑一下如果你简单地覆盖了响应变量会发生什么。在C#中,类是引用类型,变量现在引用一个新对象,旧的响应对象将消失在虚无之中,等待最终由GC进行收集而不调用Dispose。这肯定不是你想要的。
所以如果你想要重复使用变量,请确保使用Close

哪些需要关闭呢?是response、streamreader和reader吗?不包括request对吧?重复关闭同一资源会有影响吗?我在循环中调用了close,然后当它跳出循环时我想再次调用close以确保。这样可以吗? - Diane2
1
该请求未实现“IDisposable”,因此没有需要关闭的内容。其他所有内容都应正确关闭。当然,如果每次使用“Close”,您可以在循环中重复使用变量。根据循环运行的频率,您可能希望考虑更有效的替代方案。只需确保在覆盖变量或不再使用变量之前调用Close即可。这通常可以通过良好的循环设计轻松实现。 - Xaser

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