我必须显式地关闭异步http请求的ResponseStream吗?
本文关键字:请求 http ResponseStream 异步 | 更新日期: 2023-09-27 18:06:16
我有一个Azure worker角色正在运行,除了其他功能外,它每80秒左右发出一些HTTP请求。这是连续发生的。随着我们的扩展,它可能会产生更多的HTTP请求,因此我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是……我们在某个地方有内存泄漏。当这个进程运行时,它会缓慢但肯定地丢失内存,直到完全耗尽。有时GC会启动并释放一些未使用的对象,但它会继续缓慢下降的趋势。
当我们的回调执行并且我们用EndGetResponse()完成请求时,我们不触及响应流。我们需要知道的是HTTP状态码,我们将其保存为我们自己的记录。我们从不调用GetResponseStream()然后关闭它。我们做 Close() HttpWebResponse.
我的问题是:我们是否需要对响应流做一些事情,然后关闭()它?不这样做会导致内存泄漏吗?我所看到的所有MS示例/其他SO讨论都与流有关。我想知道我们是否应该添加GetResponseStream().Close()…
代码如下:
// the request state class, passed along with async request
public class RequestState
{
public HttpWebRequest Request { get; set; }
public HttpWebResponse Response { get; set; }
// some other properties to track which request this is..
}
...... in some other class .....
// code to perform the request
public void DoHttpRequest()
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://myurl.....");
RequestState state = new RequestState(req); // this just sets the Request property on RequestState
req.BeginGetResponse(OnRequestComplete, state);
}
// the callback, request has finished
public void OnRequestComplete(IAsyncResult result)
{
RequestState state = (RequestState)result.AsyncState;
HttpWebRequest req = state.Request;
state.Response = (HttpWebResponse)req.EndGetResponse(result);
// we do not care about the body of the response
// all we want is the status code, which we store somewhere else..
if (state.Response.StatusCode == HttpStatusCode.OK || state.Response.StatusCode == HttpStatusCode.Created)
{
// comm was successful
// save this result code somewhere...
}
else if (state.Response.StatusCode == HttpStatusCode.RequestTimeout || state.Response.StatusCode == HttpStatusCode.GatewayTimeout)
{
// comm timed out
// save this result code somewhere..
}
else
{
// something else, comm failed
// save this result code somewhere..
}
// we've got the relevant data from the HttpWebResponse object, dispose of it
state.Response.Close();
}
谢谢!
我检查了Reflector(。. NET 4.0最新版本,如Azure应用程序所使用):HttpWebResponse.Close
关闭GetResponseStream
返回的流。
听起来好像其他地方有问题。
从简单的看,关闭流应该也调用原来的HttpWebRequest
上的Abort
,但逻辑相当复杂。您可能想要尝试显式调用Abort
,看看内存使用是否清除。
您可以使用using语句来消费响应,确保它已被处理!如果你不打算再次阅读流内容,那么我认为关闭没有任何危害!再考虑一下:在回调中,您确定在尝试记录某个地方的结果时没有异常吗?
我遇到过和你非常相似的问题。我有一些worker角色周期性地进入Azure无法再与其通信的状态,并且当Azure实例上发生错误时,它们不会像我预期的那样重新启动。
在与MS支持人员友好交谈后,发现我们的实例内存不足。当这种情况发生时,应用程序结构控制器服务(它负责VM和VM之外的所有Azure管理人员之间的所有通信)崩溃,这意味着你无法对管理门户中的实例做任何事情。
结果是我们有一个经常使用的对象,当我们完成时没有对它调用dispose。
回答你的问题,作为一般原则如果一个对象有一个dispose方法,当你用完它的时候你应该调用dispose。
使用最新的Windows Azure分析工具来确定泄漏的内容,请参阅msdn -分析Windows Azure应用程序并使用内存分析选项。
你可以在这里从WebPI获得最新的工具