我有一个.Net Framework#4.0应用程序,使用WebRequest / WebResponse类生成大量Web请求,因为我看到它有内存泄漏(或者我做错了) 我写了一些简单的小应用程序来证明这一点:
class Program
{
public static void Main(string[] args)
{
while(true)
{
var webRequest = (HttpWebRequest)WebRequest.Create("http://www.gooogle.com");
Init(webRequest);
using (var webResponse = (HttpWebResponse)webRequest.GetResponse())
{
var responseStream = webResponse.GetResponseStream();
responseStream.ReadTimeout = 30;
var streamReader = new StreamReader(responseStream, Encoding.UTF8);
var page = streamReader.ReadToEnd();
streamReader.Close();
streamReader.Dispose();
responseStream.Close();
responseStream.Dispose();
webResponse.Close();
Console.WriteLine("Done");
//GC.Collect();
}
}
}
private static void Init (HttpWebRequest webRequest)
{
webRequest.Method = "GET";
webRequest.Host = "www.gooogle.com";
webRequest.UserAgent =
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.5; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E; InfoPath.3) chromeframe/5.0.375.62";
webRequest.Accept =
"application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
webRequest.KeepAlive = true;
}
}
我想出的唯一解决方案是使用GC.Collect()(在示例中未标记),所有对象都被丢弃,所有流都被关闭,我错过了什么?
我找到了一些东西,但我不明白原因,如果我最小化控制台内存使用量减少并看起来O.K,可能是因为Conosole或WinForm存在问题的原因,我该如何解决?
答案 0 :(得分:4)
你正在紧密循环中分配内存。您可能没有内存泄漏,您的应用程序表现不佳(从某种意义上说,它无缘无故地占用了大量系统资源。)
垃圾收集器不会打断你的循环,以便压缩释放的内存,除非由于内存压力。简单的解决方法是在循环的迭代之间引入延迟(可以像Thread.Sleep一样简单,但我不建议这样做。)
一旦你的程序不能很好地消耗所有可用的CPU时间,它应该允许GC更频繁地运行。
答案 1 :(得分:1)
试试这个:
while (true)
{
var webRequest = (HttpWebRequest) WebRequest.Create("http://www.gooogle.com");
Init(webRequest);
using (var webResponse = (HttpWebResponse) webRequest.GetResponse())
{
using (var responseStream = webResponse.GetResponseStream())
{
responseStream.ReadTimeout = 30;
using (var streamReader = new StreamReader(responseStream, Encoding.UTF8))
{
var page = streamReader.ReadToEnd();
}
}
Console.WriteLine("Done");
}
}
答案 2 :(得分:0)
是的,我们也发现了泄漏。解决方案是......小心你用这个东西做什么。考虑不使用它。我相信它有......问题(至少在3.5版本,也可能是其他版本)。哦,别忘了在Microsoft Connect上报告/投票。
答案 3 :(得分:0)
看看这个(source):
症状
当您使用
HttpWebRequest
类为HTTP POST或PUT请求发送大量数据时,该请求可能在运行Microsoft .NET Framework的计算机上失败。此外,您可能会收到内存不足的异常。您可能会注意到,使用
HttpWebRequest
类的应用程序会消耗大量内存。当您使用性能监视器监视使用HttpWebRequest类的应用程序时,随着发送数据,专用字节数将继续增加。原因
发生此问题的原因是,当您使用HttpWebRequest类时,默认情况下.NET Framework会缓冲传出数据。 KB文章http://support.microsoft.com/kb/908573记录了原始问题。
解决方案
要变通解决此问题,请将
HttpWebRequest.AllowWriteStreamBuffering
属性设置为false
。这样,用于POST或PUT请求的传出数据(实体正文)将不会在内存中进行缓冲。在版本低于4.5的Microsoft .NET Framework中,将
HttpWebRequest.AllowWriteStreamBuffering
属性设置为false
有时会在将数据上传到经过身份验证的终结点时导致错误。例如,您可能会遇到System.Net.WebException,消息为“此请求需要缓冲数据才能成功”。但是,在更深入的研究中,与异常关联的响应实际上指示状态代码为System.Net.HttpStatusCode.Unauthorized(401)。 KB文章http://support.microsoft.com/kb/908573介绍了用于处理401响应的预身份验证和KeepAlive连接的解决方法。与Microsoft .NET Framework 1.1、2.0、3.0、3.5和4.0不同,Microsoft .NET Framework 4.5为
HttpWebRequest.AllowWriteStreamBuffering
属性添加了新的设计功能。只要启用了Expect100Continue功能,新功能就可以直接处理身份验证方案。ServicePointManager.Expect100Continue
的默认值为true
。