2013-11-01 3 views
0

Я использую следующий класс GCM для отправки данных для отправки уведомления GCM около 10000 андроида устройств:пост 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"; 
    } 
} 

это используется в форме окна, которые содержат таймер и каждые 10 секунд будут тикать фон рабочий, если он не занят, чтобы получить данные из базы данных и отправить его до 10 000 Android устройств с вызова:

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

где sublist составляет не более 1000, как гсм облака квоты на каждый запрос. уведомление получено хорошо, но в программах используется большой объем памяти.

после удаления функций при попытке обнаружить основную часть проекта, которая вызывает использование плунжера (2 ГБ памяти, используемой процессом за 4 дня). Я обнаружил, что отправка уведомления вызывает это использование плунжера.

Я искал проблемы использования ram с помощью httpwebrequset и не нашел ничего связанного. Я также пытался вызвать сборщик мусора, но он не очищает всю память, большая часть которой используется; он очищает только около 5% от общей используемой памяти оперативной памяти. Может ли кто-нибудь помочь остановить это использование большой памяти.

+0

Нет ничего явно неправильного в SendGCMNotification(), я предполагаю, что утечка (если она есть) вызвана чем-то другим в приложении. Вам нужно объяснить, как вы пришли к выводу, что «я обнаружил, что отправка уведомления вызывает это использование бара». Кроме того, почему вы вызываете ServicePointManager.ServerCertificateValidationCallback каждый раз? – gooid

+0

Обязательно избавляйтесь от всего, что доступно. Например, ваш Stream, StreamReader и WebResponse. Самая безопасная ставка заключается в следующем: 'using (Stream dataStream = Request.GetRequestStream()) {...}' –

+0

@gooid Я запускаю приложение без отправки уведомления в течение 3-4 дней, а используемая память остается около 20-25 МБ, когда Я запускаю его с отправкой уведомления о возникшей проблеме. – kingk110

ответ

0

Функция GetPostData добавляет огромное количество строк. Вместо этого используйте StringBuilder.

+0

Его функция не «добавляет» к строке, она конкатенируется. Поскольку это фиксированное количество операций конкатенации, вместо StringBuilder предлагается String. 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); sb.Append (", \" time_to_live \ ": 43200, \" collapse_key \ ": \" Новости \ ", \" data \ ": {\" tickerText \ ": \" "). Добавить (this.tickerText); sb.Append ("\", \ "level \": \ ""). Добавить (this.level) .Append ("\", "); sb.Append ("\" id \ ": \" "). Добавить (this.id) .Append (" \ ","); ..... sb.Append ("\" message \ ": \" "). Добавить (this.message) .Append (" \ "}}"); строка postData = sb.ToString(); return postData; Я попробую – kingk110

+0

такой же результат; через 3 часа он использует 168 МБ – kingk110

Смежные вопросы