What is making this code eat up all memory on iOS?
I'm calling the method below and it makes iOS memory go up from 40MB to 160MB and it won't come down again. Executing it again kills the app because it is OOM. I have tried everything but I cannot see a problem with it. It is calling a webservice which returns quite a lot of data (5MB to 10MB) string. I just want to read it and store it in a file.
public void GetDataStreamed ( int iID, string sFilename )
{
string sUrl = "somewebservice.com/somemethod" ;
WebRequest request = WebRequest.Create ( sUrl );
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = "sSessionID=" + this.SessionID + "&iID=" + iID.ToString ( ) + "&iDepth=-1&iRootID=-1&aObjectTypes=2&aObjectTypes=3&aObjectTypes=4&aObjectTypes=6";
byte[] byteArray = Encoding.UTF8.GetBytes ( postData );
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
request.Timeout = 60000;
// Get the request stream.
using(Stream dataStream = request.GetRequestStream ( ))
{
// Write the data to the request stream.
dataStream.Write ( byteArray, 0, byteArray.Length );
// Close the Stream object.
dataStream.Close ( );
}
// Read response and stream into a file.
HttpWebResponse oResponse = ( HttpWebResponse ) request.GetResponse ( );
Stream oResponseStream = oResponse.GetResponseStream ( );
using ( StreamWriter oFileWriter = new StreamWriter ( sFilename ) )
{
using ( StreamReader oReader = new StreamReader ( oResponseStream ) )
{
while ( !oReader.EndOfStream )
{
string s = oReader.ReadLine ( );
oFileWriter.WriteLine ( System.Web.HttpUtility.HtmlDecode ( s ) );
oFileWriter.Flush();
}
oReader.Close ( );
}
oFileWrite开发者_如何学Gor.Close();
}
}
I just stumbled on this post, and you may have already figured this out by now. In the snippet of code you provided you are not Disposing of the following objects that should be in using blocks:
- WebRequest
- HttpWebResponse
- Stream
Once you left the method the memory used by those is still being reserved and will not be garbage collected.
As a side note, Dispose() does close out the connection which one of the reasons for the syntactic sugar of the using statement is so you do not have to remember to call close. Also you can stack using statements without braces if they have no body other than another using statement. Here is a quick and dirty refactor of the sample you provided with the missing using statements. This should correct the memory leak you are experiencing.
public void GetDataStreamed(int iID, string sFilename)
{
string sUrl = "somewebservice.com/somemethod" ;
using (WebRequest request = WebRequest.Create (sUrl))
{
// Set the Method property of the request to POST.
request.Method = "POST";
// Create POST data and convert it to a byte array.
string postData = "sSessionID=" + this.SessionID + "&iID=" + iID.ToString() + "&iDepth=-1&iRootID=-1&aObjectTypes=2&aObjectTypes=3&aObjectTypes=4&aObjectTypes=6";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
request.Timeout = 60000;
// Get the request stream.
using(Stream dataStream = request.GetRequestStream())
{
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
}
// Read response and stream into a file.
using(HttpWebResponse oResponse = (HttpWebResponse) request.GetResponse ( ))
using(Stream oResponseStream = oResponse.GetResponseStream ())
using(StreamWriter oFileWriter = new StreamWriter (sFilename))
using(StreamReader oReader = new StreamReader (oResponseStream))
{
while(!oReader.EndOfStream)
{
string s = oReader.ReadLine();
oFileWriter.WriteLine (System.Web.HttpUtility.HtmlDecode(s));
oFileWriter.Flush();
}
}
}
}
If all you need is to download this into a file, use WebClient().DownloadFile () instead.
Are you using explicit .Close()'s to make sure you are closing the readers and writers? I thought the Using{}'s did that for you?
精彩评论