2013-11-01 20 views
0

我使用下面的GCM類數據發佈到GCM通知發送至大約10,000 Android設備:後的HttpWebRequest在C#中使用大量的內存

class GCMandroid 
{ 
    private JArray RegIDs; 
    private string tickerText; 
    private string level; 
    private string id; 
    private string title; 
    private string message; 
    private string date; 

    public GCMandroid(List<string> Ids,string tickerText,string level,string id, 
     string title,string message,string date) 
    { 
     this.RegIDs = new JArray(Ids.ToArray()); 
     this.tickerText = tickerText; 
     this.level = level; 
     this.id = id; 
     this.date = date; 
     this.title = title; 
     this.message = message; 
    } 
    public string GetPostData() 
    { 
     string postData = 
      "{ \"registration_ids\": " + this.RegIDs + ", " + 
      "\"time_to_live\":" + "43200" + ", " + 
      "\"collapse_key\":\"" + "Key" + "\", " + 
      "\"data\": {\"tickerText\":\"" + this.tickerText + "\", " + 
      "\"level\":\"" + this.level + "\", " + 
      "\"id\":\"" + this.id + "\", " + 
      "\"date\":\"" + this.date + "\", " + 
      "\"title\":\"" + this.title + "\", " + 
      "\"message\": \"" + this.message + "\"}}"; 
     return postData; 
    } 
    public bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
    { 
     return true; 
    } 

    public string SendGCMNotification(string apiKey, string postData, string postDataContentType = "application/json") 
    { 
     ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate); 

     // 
     // MESSAGE CONTENT 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 

     // 
     // CREATE REQUEST 
     HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send"); 
     Request.Method = "POST"; 
     Request.KeepAlive = false; 
     Request.ContentType = postDataContentType; 
     Request.Headers.Add(string.Format("Authorization: key={0}", apiKey)); 
     Request.ContentLength = byteArray.Length; 

     Stream dataStream = Request.GetRequestStream(); 
     dataStream.Write(byteArray, 0, byteArray.Length); 
     dataStream.Close(); 

     // 
     // SEND MESSAGE 
     try 
     { 
      WebResponse Response = Request.GetResponse(); 
      HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode; 
      if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden)) 
      { 
       var text = "Unauthorized - need new token"; 
      } 
      else if (!ResponseCode.Equals(HttpStatusCode.OK)) 
      { 
       var text = "Response from web service isn't OK"; 
      } 

      StreamReader Reader = new StreamReader(Response.GetResponseStream()); 
      string responseLine = Reader.ReadToEnd(); 
      Reader.Close(); 
      Response.Close(); 
      return responseLine; 
     } 
     catch (Exception e) 
     { 
     } 
     return "error"; 
    } 
} 

,這是在包含一個Windows窗體使用計時器每10秒鐘即可將蜱後臺工作,如果它不是忙着從數據庫中提取數據,並將其與調用發送至大約10,000 Android設備:

GCMandroid gcm = new GCMandroid(sublist, tickerText, level, id, title, message,date); 
gcm.SendGCMNotification(AndroidApiKey, gcm.GetPostData()); 

其中sublist爲max 1000按每個GCM雲配額請求。通知收到良好,但程序使用大量的內存。

在嘗試檢測導致RAM使用的項目主要部分(進程在4天內使用2 GB內存)時刪除函數之後,我發現發送通知導致此RAM的使用。

我用httpwebrequset搜索了ram用法的問題,但沒有找到任何相關的內容。我也嘗試調用垃圾回收器,但它並沒有清除大部分保持使用的所有內存;它僅清除使用的總RAM內存的大約5%。任何人都可以幫助阻止這種大量的內存使用。

+0

SendGCMNotification()沒有什麼明顯的錯誤,我的猜測是泄漏(如果有的話)是由應用程序中的其他內容引起的。你需要解釋你是如何得出結論的:「我發現發送通知導致這個RAM的使用。」 另外,爲什麼每次調用ServicePointManager.ServerCertificateValidationCallback? – gooid

+0

一定要處置一次性的東西。例如,您的Stream,StreamReader和WebResponse。最安全的賭注是:'使用(Stream dataStream = Request.GetRequestStream()){...}' –

+0

@ gooid我啓動應用程序時不發送通知3-4天,使用的內存保持在20-25 MB左右我發送通知發送問題發生。 – kingk110

回答

0

GetPostData函數附加了大量的字符串。改用StringBuilder。

+0

他的功能不是「追加」到一個字符串,它是連接的。由於它是一個固定數量的串聯操作,所以建議使用String而不是StringBuilder。 http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=vs.110).aspx –

+0

新的GetPostData是: StringBuilder sb = new StringBuilder(); sb.Append(「{\」registration_ids \「:」).Append(this.RegIDs); (「,\」time_to_live \「:43200,\」collapse_key \「:\」News \「,\」data \「:{\」tickerText \「:\」「)。Append(this.tickerText ); sb.Append(「\」,\「level \」:\「」)。Append(this.level).Append(「\」,「); (「\」id \「:\」「)。Append(this.id).Append(」\「,」); ..... sb.Append(「\」message \「:\」「)。Append(this.message).Append(」\「}}」); string postData = sb.ToString(); return postData; 我會嘗試 – kingk110

+0

相同的結果;在3小時內它使用168 MB – kingk110