title: Memory Leak In C# Windows Service For Sending Emails
body: <p>This seems to be a pretty popular problem/question these days but I cannot seem to find a solution to the problem.</p>
  
  <p>I have created a simple windows service in c# for sending out emails. The app works great except for it's memory usage. The front end of the app is web based and the service is queued by a text file being created in a directory. After reading the text file the service gathers the newsletter info and email addresses from MS SQL db and commences to send out 1 email every 4 seconds. While watching the service run through task manager, you can see the cpu usage bump up every 4 seconds but immediately drop back down. The memory on the other hand seems to bump up not every email but every 3-4 emails by 50-75k. This will continue to increment until all emails are sent. I just sent out approx. 2100 emails and the memory usage was up to 100MB. Another thing I have noticed is that after all emails are sent, the memory usage will hold at this total until I restart the service. When the service is idling, the memory runs at about 6500k. Anyone have any suggestions as to how I can get this memory usage down and disposed of after the mailings complete? My code is below. Any help would be greatly appreciated..</p>
  
  <pre><code>namespace NewsMailer
  {
      public partial class NewsMailer : ServiceBase
      {
          private FileSystemWatcher dirWatcher;
          private static string filePath = @"E:\Intranets\Internal\Newsletter\EmailQueue";
          private static string attachPath = @"E:\Intranets\Internal\Newsletter\Attachments";
          private string newsType = String.Empty;
          private string newsSubject = String.Empty;
          private string newsContent = String.Empty;
          private string userName = String.Empty;
          private string newsAttachment = "";
          private int newsID = 0;
          private int emailSent = 0;
          private int emailError = 0;
  
          public NewsMailer()
          {
              InitializeComponent();
          }
  
          protected override void OnStart(string[] args)
          {
              dirWatcher = new FileSystemWatcher();
              dirWatcher.Path = filePath;
              dirWatcher.Created += new FileSystemEventHandler(ReadText);
              dirWatcher.EnableRaisingEvents = true;
          }
  
          protected override void OnStop()
          {
              dirWatcher.EnableRaisingEvents = false;
              dirWatcher.Dispose();
          }
  
          private void ClearVar()
          {
              newsType = String.Empty;
              newsSubject = String.Empty;
              newsContent = String.Empty;
              userName = String.Empty;
              newsAttachment = "";
              newsID = 0;
              emailSent = 0;
              emailError = 0;
          }
  
          private void ReadText(object sender, FileSystemEventArgs e)
          {
              ClearVar();
              SetLimits();
              string txtFile = filePath + @"\QueueEmail.txt";
              StreamReader sr = new StreamReader(txtFile);
              string txtLine = String.Empty;
  
              try
              {
                  while ((txtLine = sr.ReadLine()) != null)
                  {
                      string[] lineCpl = txtLine.Split('§');
                      newsType = lineCpl[0];
                      userName = lineCpl[1];
                      newsID = Convert.ToInt32(lineCpl[2]);
                  }
              }
              catch (IOException ex)
              {
                  SendExByMail("ReadText() IO Error", ex);
              }
              catch (Exception ex)
              {
                  SendExByMail("ReadText() General Error", ex);
              }
              finally
              {
                  sr.Close();
                  sr.Dispose();
              }
              GetNews();
          }
  
          [DllImport("kernel32.dll")]
          public static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);
  
          private void SetLimits()
          {
              GC.Collect();
              GC.WaitForPendingFinalizers();
  
              if (Environment.OSVersion.Platform == PlatformID.Win32NT)
                  SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
  
          }
  
          private void DeleteText()
          {
              try
              {
                  File.Delete(filePath + @"\QueueEmail.txt");
              }
              catch (IOException ex)
              {
                  SendExByMail("DeleteText() IO Error", ex);
              }
              catch (Exception ex)
              {
                  SendExByMail("DeleteText() General Error", ex);
              }
          }
  
          private void GetNews()
          {
              string connectionString = ConfigurationManager.ConnectionStrings["contacts"].ConnectionString;
              SqlConnection conn = new SqlConnection(connectionString);
  
              string sqlSELECT = "SELECT newsSubject, newsContents, username, attachment FROM newsArchive " +
                                 "WHERE ID = " + newsID;
  
              SqlCommand comm = new SqlCommand(sqlSELECT, conn);
  
              try
              {
                  conn.Open();
                  using (SqlDataReader reader = comm.ExecuteReader())
                  {
                      while (reader.Read())
                      {
                          newsSubject = reader[0].ToString();
                          newsContent = reader[1].ToString();
                          userName = reader[2].ToString();
                          newsAttachment = reader[3].ToString();
                      }
                      reader.Dispose();
                  }
              }
              catch (SqlException ex)
              {
                  SendExByMail("GetNews() SQL Error", ex);
              }
              catch (Exception ex)
              {
                  SendExByMail("GetNews() General Error", ex);
              }
              finally
              {
                  comm.Dispose();
                  conn.Dispose();
              }
              DeleteText();
              GetAddress();
          }
  
          private void GetAddress()
          {
              string connectionString = ConfigurationManager.ConnectionStrings["contacts"].ConnectionString;
              SqlConnection conn = new SqlConnection(connectionString);
  
              string sqlSELECT = String.Empty;
              if (newsType == "custom")
                  sqlSELECT = "SELECT DISTINCT email FROM custom";
              else
                  sqlSELECT = "SELECT DISTINCT email FROM contactsMain WHERE queued = 'True'";
  
              SqlCommand comm = new SqlCommand(sqlSELECT, conn);
  
              try
              {
                  conn.Open();
                  using (SqlDataReader reader = comm.ExecuteReader())
                  {
                      while (reader.Read())
                      {
                          try
                          {
                              if (CheckEmail(reader[0].ToString()) == true)
                              {
                                  SendNews(reader[0].ToString());
                                  Thread.Sleep(4000);
                                  emailSent++;
                              }
                              else
                              {
                                  SendInvalid(reader[0].ToString());
                                  emailError++;
                              }
                          }
                          catch (SmtpException ex)
                          {
                              SendExByMail("NewsLetter Smtp Error", reader[0].ToString(), ex);
                              emailError++;
                          }
                          catch (Exception ex)
                          {
                              SendExByMail("Send NewsLetter General Error", reader[0].ToString(), ex);
                              emailError++;
                          }
                          finally
                          {
                              UnqueueEmail(reader[0].ToString());
                          }
  
                      }
                      reader.Dispose();
                  }
              }
              catch (SqlException ex)
              {
                  SendExByMail("GetAddress() SQL Error", ex);
              }
              catch (Exception ex)
              {
                  SendExByMail("GetAddress() General Error", ex);
              }
              finally
              {
                  comm.Dispose();
                  conn.Dispose();
              }
  
              SendConfirmation();
          }
  
          private bool CheckEmail(string emailAddy)
          {
              bool returnValue = false;
              string regExpress = @"^[\w-]+(?:\.[\w-]+)*@(?:[\w-]+\.)+[a-zA-Z]{2,7}$";
  
              Match verifyE = Regex.Match(emailAddy, regExpress);
              if (verifyE.Success)
                  returnValue = true;
              return returnValue;
          }
  
          private void SendNews(string emailAddy)
          {
              string today = DateTime.Today.ToString("MMMM d, yyyy");
  
              using (MailMessage message = new MailMessage())
              {
                  SmtpClient smtpClient = new SmtpClient();
  
                  MailAddress fromAddress = new MailAddress("");
  
                  message.From = fromAddress;
                  message.To.Add(emailAddy);
                  message.Subject = newsSubject;
  
                  if (newsAttachment != "")
                  {
                      Attachment wusaAttach = new Attachment(attachPath + newsAttachment);
                      message.Attachments.Add(wusaAttach);
                  }
  
                  message.IsBodyHtml = true;
                  #region Message Body
                  message.Body = "";
                  #endregion
  
                  smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                  smtpClient.Host = "";
                  smtpClient.Credentials = new System.Net.NetworkCredential("");
  
                  smtpClient.Send(message);
                  smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
              }
          }
  
          private void UnqueueEmail(string emailAddy)
          {
              string connectionString = ConfigurationManager.ConnectionStrings["contacts"].ConnectionString;
              SqlConnection conn = new SqlConnection(connectionString);
              string sqlStatement = String.Empty;
  
              if (newsType == "custom")
                  sqlStatement = "UPDATE custom SET queued = 'False' WHERE email LIKE '" + emailAddy + "'";
              else
                  sqlStatement = "UPDATE contactsMain SET queued = 'False' WHERE email LIKE '" + emailAddy + "'";
  
              SqlCommand comm = new SqlCommand(sqlStatement, conn);
  
              try
              {
                  conn.Open();
                  comm.ExecuteNonQuery();
              }
              catch (SqlException ex)
              {
                  SendExByMail("UnqueueEmail() SQL Error", ex);
              }
              catch (Exception ex)
              {
                  SendExByMail("UnqueueEmail() General Error", ex);
              }
              finally
              {
                  comm.Dispose();
                  conn.Dispose();
              }
          }
  
          private void SendConfirmation()
          {
              SmtpClient smtpClient = new SmtpClient();
  
              using (MailMessage message = new MailMessage())
              {
                  MailAddress fromAddress = new MailAddress("");
                  MailAddress toAddress = new MailAddress();
  
                  message.From = fromAddress;
                  message.To.Add(toAddress);
                  //message.CC.Add(ccAddress);
                  message.Subject = "Your Newsletter Mailing Has Completed";
                  message.IsBodyHtml = true;
                  message.Body = "Total Emails Sent: " + emailSent +
                                 "&lt;br /&gt;Total Email Errors: " + emailError +
                                 "&lt;br /&gt;Contact regarding email errors if any were found";
  
                  smtpClient.Host = "";
                  smtpClient.Credentials = new System.Net.NetworkCredential("");
                  smtpClient.Send(message);
                  smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
              }
              ClearVar();
              System.GC.Collect();
          }
  
          private void SendInvalid(string emailAddy)
          {
              SmtpClient smtpClient = new SmtpClient();
  
              using (MailMessage message = new MailMessage())
              {
                  MailAddress fromAddress = new MailAddress("");
                  MailAddress toAddress = new MailAddress("");
  
                  message.From = fromAddress;
                  message.To.Add(toAddress);
                  //message.CC.Add(ccAddress);
                  message.Subject = "Invalid Email Address";
                  message.IsBodyHtml = true;
                  message.Body = "An invalid email address has been found, please check the following " +
                                 "email address:&lt;br /&gt;" + emailAddy;
  
                  smtpClient.Host = "";
                  smtpClient.Credentials = new System.Net.NetworkCredential("");
                  smtpClient.Send(message);
                  smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
              }
          }
  
          private void SendExByMail(string subject, Exception ex)
          {
              SmtpClient smtpClient = new SmtpClient();
  
              using (MailMessage message = new MailMessage())
              {
                  MailAddress fromAddress = new MailAddress("");
                  MailAddress toAddress = new MailAddress("");
  
                  message.From = fromAddress;
                  message.To.Add(toAddress);
                  //message.CC.Add(ccAddress);
                  message.Subject = subject;
                  message.IsBodyHtml = true;
                  message.Body = "An Error Has Occurred: &lt;br /&gt;Exception: &lt;br /&gt;" + ex.ToString();
  
                  smtpClient.Host = "";
                  smtpClient.Credentials = new System.Net.NetworkCredential("");
                  smtpClient.Send(message);
                  smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
              }
          }
  
          private void SendExByMail(string subject, string body, Exception ex)
          {
              SmtpClient smtpClient = new SmtpClient();
  
              using (MailMessage message = new MailMessage())
              {
                  MailAddress fromAddress = new MailAddress("", "MailerService");
                  MailAddress toAddress = new MailAddress("");
  
                  message.From = fromAddress;
                  message.To.Add(toAddress);
                  //message.CC.Add(ccAddress);
                  message.Subject = subject;
                  message.IsBodyHtml = true;
                  message.Body = "An Error Has Occurred:&lt;br /&gt;&lt;br /&gt;" + body + "&lt;br /&gt;&lt;br /&gt;Exception: &lt;br /&gt;" + ex.ToString();
  
                  smtpClient.Host = "";
                  smtpClient.Credentials = new System.Net.NetworkCredential("");
                  smtpClient.Send(message);
                  smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
              }
          }
      }
  }
  </code></pre>