C# 我必须显式关闭异步http请求的ResponseStream吗?
我有一个Azure worker角色正在运行,除了其他功能外,它每隔80秒左右发出一次HTTP请求。这种情况不断发生。随着我们的扩展,它可能会发出更多的HTTP请求,因此我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是。。。我们某处有内存泄漏。当这个过程运行时,它会缓慢但肯定会丢失内存,直到完全耗尽为止。有时GC会启动并释放一些未使用的对象,但它会继续其缓慢的下降趋势 当我们执行回调并使用EndGetResponse()完成请求时,我们不接触响应流。我们所需要知道的只是HTTP状态码,我们将其保存为自己的记录。我们从不调用GetResponseStream()并随后关闭它。我们确实关闭了HttpWebResponse 我的问题是:我们需要对响应流做些什么,然后关闭它吗?这样做不会导致内存泄漏吗?我所看到的所有MS示例/其他SO讨论都与流有关。我想知道是否应该添加GetResponseStream().Close() 代码如下:C# 我必须显式关闭异步http请求的ResponseStream吗?,c#,http,memory,asynchronous,azure,C#,Http,Memory,Asynchronous,Azure,我有一个Azure worker角色正在运行,除了其他功能外,它每隔80秒左右发出一次HTTP请求。这种情况不断发生。随着我们的扩展,它可能会发出更多的HTTP请求,因此我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是。。。我们某处有内存泄漏。当这个过程运行时,它会缓慢但肯定会丢失内存,直到完全耗尽为止。有时GC会启动并释放一些未使用的对象,但它会继续其缓慢的下降趋势 当我们执行回调并使用EndGetResponse()完成请求时,我们不接触响应流。
// 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()。谢谢你的回复。