2011-10-22 69 views
0

我有一個基於MonoTouch的iOS通用應用程序。它使用REST服務進行調用以獲取數據。我使用HttpWebRequest類來構建和打電話。一切都很好,除了它似乎保持了記憶。我已經在代碼中使用了限制事物的範圍。我避免了匿名代表以及我聽說他們可能成爲問題。我有一個助手類,它可以建立我對REST服務的呼叫。當我打電話時,似乎只是通過撥打我的電話來保持記憶。我很好奇,如果有人遇到類似的問題與HttpWebClient和如何處理它。我目前正在查看是否可以使用nsMutableRequest進行調用,並避免使用HttpWebClient,但我正在努力使其與NTLM身份驗證一起工作。任何建議表示讚賞。HttpWebClient在MonoTouch中使用高內存

protected T IntegrationCall<T,I>(string methodName, I input) { 
HttpWebRequest invokeRequest = BuildWebRequest<I>(GetMethodURL(methodName),"POST",input, true); 
WebResponse response = invokeRequest.GetResponse(); 

T result = DeserializeResponseObject<T>((HttpWebResponse)response); 
invokeRequest = null; 
response = null; 
return result; 
} 

protected HttpWebRequest BuildWebRequest<T>(string url, string method, T requestObject, bool IncludeCredentials) 
{ 
ServicePointManager.ServerCertificateValidationCallback = Validator; 

     var invokeRequest = WebRequest.Create(url) as HttpWebRequest; 
     if (invokeRequest == null) 
      return null; 

     if (IncludeCredentials) 
     { 
      invokeRequest.Credentials = CommonData.IntegrationCredentials; 
     } 

     if(!string.IsNullOrEmpty(method)) 
      invokeRequest.Method = method; 
     else 
      invokeRequest.Method = "POST"; 
     invokeRequest.ContentType = "text/xml"; 
     invokeRequest.Timeout = 40000; 

     using(Stream requestObjectStream = new MemoryStream()) 
     { 
      DataContractSerializer serializedObject = new DataContractSerializer(typeof(T)); 
      serializedObject.WriteObject(requestObjectStream, requestObject); 

      requestObjectStream.Position = 0; 
      using(StreamReader reader = new StreamReader(requestObjectStream)) 
      { 
       string strTempRequestObject = reader.ReadToEnd(); 

       //byte[] requestBodyBytes = Encoding.UTF8.GetBytes(strTempRequestObject); 
       Encoding enc = new UTF8Encoding(false); 
       byte[] requestBodyBytes = enc.GetBytes(strTempRequestObject); 

       invokeRequest.ContentLength = requestBodyBytes.Length; 

       using (Stream postStream = invokeRequest.GetRequestStream()) 
       { 
        postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length); 
       } 
      } 
     } 

     return invokeRequest; 
    } 
+0

您是否嘗試過使用內存分析器?您使用的數據有多大? – svick

回答

1

使用使用是做正確的事 - 但你的代碼看起來相同的內容多次(它不應該這樣做),被複制。

requestObjectStream變成string然後在寫入另一個流之前變成byte[]。考慮到額外的代碼(例如,ReadToEndUTF8Encoding.GetBytes)可能自己分配的內容(例如更多的strings,byte [] ...),這就是而不是

所以,如果你序列化很大,那麼你會消耗大量額外的內存(沒有)。對於stringbyte[],它甚至更糟,因爲您無法手動處理它們(GC將決定何時進行測量,難度更大)。

我會嘗試(但沒有;-)類似:

... 

    using (Stream requestObjectStream = new MemoryStream()) { 
     DataContractSerializer serializedObject = new DataContractSerializer(typeof(T)); 
     serializedObject.WriteObject(requestObjectStream, requestObject); 
     requestObjectStream.Position = 0; 

     invokeRequest.ContentLength = requestObjectStream.Length; 
     using (Stream postStream = invokeRequest.GetRequestStream()) 
      requestObjectStream.CopyTo (postStream); 
    } 

    ... 

這將讓MemoryStream拷貝自身到請求流。另一種方法是撥打ToArrayMemoryStream(但這是GC必須跟蹤和釋放的序列化對象的另一個副本)。

+0

通常被攔截的唯一字符串是代碼中的編譯時常量。你爲什麼認爲這些大字符串會被禁用? – svick

+0

你是對的,有重複的活動在那裏,我不需要這是從一些調試遺留下來。我刪除了字符串 - >字節 - >後期流的額外步驟。至少該代碼更有效。但是,我沒有看到內存的下降。你有沒有看到HttpWebClient的任何問題,或者你認爲我有可能追逐錯誤的東西? –

+0

@svick:好點,我對'string'的評論太過分了( - 問題):我修改了我的答案以保持主題@Mark很難說,你的序列化對象是否很大(如果是的話你應該看看有些區別)?我們也不知道你如何測量你的內存消耗(工具/技術)? – poupou