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

C# 我必须显式关闭异步http请求的ResponseStream吗?,c#,http,memory,asynchronous,azure,C#,Http,Memory,Asynchronous,Azure,我有一个Azure worker角色正在运行,除了其他功能外,它每隔80秒左右发出一次HTTP请求。这种情况不断发生。随着我们的扩展,它可能会发出更多的HTTP请求,因此我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是。。。我们某处有内存泄漏。当这个过程运行时,它会缓慢但肯定会丢失内存,直到完全耗尽为止。有时GC会启动并释放一些未使用的对象,但它会继续其缓慢的下降趋势 当我们执行回调并使用EndGetResponse()完成请求时,我们不接触响应流。

我有一个Azure worker角色正在运行,除了其他功能外,它每隔80秒左右发出一次HTTP请求。这种情况不断发生。随着我们的扩展,它可能会发出更多的HTTP请求,因此我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是。。。我们某处有内存泄漏。当这个过程运行时,它会缓慢但肯定会丢失内存,直到完全耗尽为止。有时GC会启动并释放一些未使用的对象,但它会继续其缓慢的下降趋势

当我们执行回调并使用EndGetResponse()完成请求时,我们不接触响应流。我们所需要知道的只是HTTP状态码,我们将其保存为自己的记录。我们从不调用GetResponseStream()并随后关闭它。我们确实关闭了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();
}

谢谢大家!

您可以使用using语句来使用响应,确保它已被释放!如果你不打算再次阅读流的内容,那么我认为在结束时没有任何伤害!再想一想:在您的回调中,您确定在某些地方记录结果时没有异常吗?

我签入了Reflector(.NET 4.0最新版本,由Azure应用程序使用):
HttpWebResponse.Close
会关闭
GetResponseStream
返回的流

听起来好像其他地方有问题


简单地看,关闭流还应该对原始的
HttpWebRequest
调用
Abort
,但逻辑相当复杂。您可能希望尝试显式调用
Abort
,查看内存使用情况是否已清除。

我遇到了与您非常类似的问题。我有一些工作人员角色定期进入Azure无法再与其通信的状态,并且当Azure实例发生错误时,他们不会像我预期的那样重新启动

在与MS support的人员进行友好交谈后,我们发现我们的实例内存不足。当这种情况发生时,app fabric controller服务(完成VM与VM之外的所有Azure管理内容之间的所有对话)崩溃,这意味着您无法对管理门户中的实例执行任何操作

事实证明,我们有一个经常使用的对象,我们在完成时没有调用dispose


因此,在回答您的问题时,作为一个一般原则,如果对象具有dispose方法,当您使用完它时,应该调用dispose

要查明泄漏的内容,请使用适用于Windows Azure的最新分析工具,请参阅msdn-并使用内存分析选项


您可以从

获得最新的工具是的,使用语句肯定是更好的方法。我们有一些我遗漏的try-catch块,我们成功地保存了HTTP代码,所以看起来好像没有发生异常。但使用是最安全的方式。我希望有人能告诉我们是否必须关闭()流,如果是的话,为什么不关闭()来处理顶级HttpWebResponse?在这种情况下,我会做一个内存分析!我没有与Azure合作过,但考虑到你的应用程序可以随时扩展,所以不难使用内存配置文件,只要使用此逻辑就可以确保你没有遗漏任何内容!“直到它完全用完”-您是否得到
OutOfMemoryException
?因为它在Azure云上,所以我当时无法跟踪实际的行为。我们对HTTP状态代码的存储时间从每80秒增加到更长,然后角色“降级”并完全停止运行。每隔10秒对角色的可用内存进行一次分析,结果显示内存呈下降趋势,直到达到0。。不过需要几天时间。感谢您检查反射器;我没想到。Abort()是否会像原始HttpWebRequest对象上的Dispose()一样工作?我在任何示例()中都没有看到过该调用,但它确实值得一试。它看起来确实清理了一些资源,但实际上它不是一个
Dispose
,因为它通常不被调用。在处理System.IO.Compression.GZipStream对象时发现了类似的问题。调用request.Abort()首先解决了这个问题。是的,这听起来很熟悉。我们将开始使用“using”语句,因为它确保即使异常中断流,也会调用Dispose()。谢谢你的回复。