我有一个Azure工作者角色,在其他函数中,它每80秒左右发出一些HTTP请求。这种情况时有发生。随着我们的扩展,它可能会产生更多的HTTP请求,所以我编写了使用BeginGetResponse、EndGetResponse和回调的代码。问题是..。我们在某个地方有记忆泄露。当这个过程运行时,它会缓慢但肯定地失去记忆,直到完全耗尽。有时GC会启动并释放一些未使用的对象,但是它继续其缓慢的下降趋势。
当我们的回调执行并且用EndGetResponse()完成请求时,我们不会触及响应流。我们所需要知道的就是HTTP状态代码,我们将其保存在自己的记录中。我们从不调用GetResponseStream()并随后关闭它。我们确实关闭了() HttpWebResponse。
我的问题是:我们需要对Response做些什么,然后关闭它吗?这样做不会导致内存泄漏吗?所有MS示例/其他,所以我看到的讨论对流做了一些事情。我想知道我们是否应该添加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();
}谢谢!
发布于 2011-08-22 18:18:27
我签入了Reflector ( Azure应用程序使用的.NET 4.0最新版本):HttpWebResponse.Close确实关闭了GetResponseStream返回的流。
听起来好像其他地方出了什么问题。
简单地看,关闭流也应该在原始的Abort上调用HttpWebRequest,但是逻辑非常复杂。您可能需要尝试显式调用Abort并查看内存使用是否已清除。
发布于 2011-08-22 17:44:09
您可以使用using语句来使用响应,确保它被释放了!如果你不打算再读一遍流的内容,我看不出有什么坏处!再想一想:在回调中,您确定在尝试记录结果时没有异常吗?
发布于 2011-08-22 21:34:57
我遇到了一个和你非常相似的问题。我有一些员工角色,它们会周期性地进入Azure无法再与其通信的状态,并且它们不会像我预期的那样重新启动,当Azure实例上发生错误时,它们会重新启动。
在与MS support的人进行了友好的交谈之后,结果发现我们的实例正在耗尽内存。当这种情况发生时,app控制器服务(它会在VM和VM之外的Azure管理工具之间进行所有的交谈)崩溃,这意味着您不能对管理门户中的实例做任何事情。
结果发现,我们有一个非常经常使用的对象,当我们完成任务时,我们并没有调用dispose。
因此,在回答您的问题时,作为一个一般原则,如果一个对象有一个dispose方法,那么当您完成处理它时,您应该调用dispose。
https://stackoverflow.com/questions/7151237
复制相似问题