我必须显式地关闭异步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();
}

谢谢!

我必须显式地关闭异步http请求的ResponseStream吗?

我检查了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获得最新的工具