WebRequest/WebResponse Memory leak
I have an .Net Framework #4.0 application that makes a large number of web requests using the WebRequest/WebResponse classes , as i see it has memory leak (or maybe i am doing something wrong) I Wrote some small simple application that demonstrates this:
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;
}
}
The only one solution i came u开发者_C百科p with is use GC.Collect() (unmarked in example) , All the object are disposed , all streams are closed , am I missing something ?
I found something but i don't understand the reason , if i minimize Console the memory usage decreases and looks O.K , what can be the reason for that is there a problem with Conosole or WinForm , how can i fix it ?
You're allocating memory in a tight loop. You probably don't have a memory leak, you have a poorly behaved application (in the sense that it's using up lots of system resources for no reason.)
The garbage collector is not going to interrupt your loop in order to compact freed memory unless it has to due to memory pressure. The simple fix would be to introduce a delay between iterations of the loop (could be as simple as Thread.Sleep, though I don't recommend that.)
Once your program is not working so hard to consume all available CPU time it should allow the GC to run more frequently.
Try this:
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");
}
}
Have a look at this (source):
Symptoms
When you use the
HttpWebRequest
class to send lots of data for a HTTP POST or PUT request, the request may fail on a computer that is running the Microsoft .NET Framework. Additionally, you may receive an out-of-memory exception.You may notice that the application that uses the
HttpWebRequest
class consumes lots of memory. When you use Performance Monitor to monitor the application that uses the HttpWebRequest class, the Private Bytes count will continue to increase as data is sent.Cause
This issue occurs because the .NET Framework buffers the outgoing data by default when you use the HttpWebRequest class. KB article http://support.microsoft.com/kb/908573 documents the original issue.
Resolution
To work around this issue, set the
HttpWebRequest.AllowWriteStreamBuffering
property tofalse
. By doing this, outgoing data (entity body) for the POST or the PUT request will not be buffered in memory.In versions of Microsoft .NET Framework earlier than 4.5, setting
HttpWebRequest.AllowWriteStreamBuffering
property tofalse
would sometimes result in errors when uploading data to authenticated endpoints. For example, you might encounter a System.Net.WebException with the message "This request requires buffering data to succeed". However on deeper investigation the response associated with the exception actually indicates a status code of System.Net.HttpStatusCode.Unauthorized (401). KB article http://support.microsoft.com/kb/908573 documents a workaround of pre-authentication and KeepAlive connection to handle 401 response.Unlike Microsoft .NET Framework 1.1, 2.0, 3.0, 3.5 and 4.0, Microsoft .NET Framework 4.5 adds new design functionality for the
HttpWebRequest.AllowWriteStreamBuffering
property. The new functionality can handle the authentication scenario directly as long as the Expect100Continue feature is enabled. The defaultServicePointManager.Expect100Continue
value istrue
.
Yes, we found a leak too. The solution is... be careful what you do with this thing. Consider not using it. I believe it has... issues (at least in 3.5, presumably other versions too). Oh, and dont forget to report it/ vote on it at Microsoft Connect.
精彩评论