This is a pretty popular problem / question these days, but I can't find a solution to the problem.
I created a simple Windows service in C # to send emails. The application works fine except for memory usage. The external interface of the application is based on the web interface, and the service is queued using a text file created in the directory. After reading a text file, the service collects newsletter information and email addresses from the MS SQL db database and starts sending 1 email every 4 seconds. Watching the service start through the task manager, you can see how the processor performance increases every 4 seconds, but is immediately discarded. Memory, on the other hand, does not seem to encourage every email, but every 3-4 letters for 50-75 thousand. This will continue until all emails are sent.I just sent out approx. 2100 letters and memory usage was up to 100 MB. Another thing that I noticed is that after sending emails, the memory usage will be held in that amount until I restart the service. When the service is idling, the memory runs at about 6,500 thousand. Does anyone have any suggestions on how I can get rid of this memory usage and recycle after the distribution is complete? My code is below. Any help would be greatly appreciated.When the service is idling, the memory runs at about 6,500 thousand. Does anyone have any suggestions on how I can get rid of this memory usage and recycle after the distribution is complete? My code is below. Any help would be greatly appreciated.When the service is idling, the memory runs at about 6,500 thousand. Does anyone have any suggestions on how I can get rid of this memory usage and recycle after the distribution is complete? My code is below. Any help would be greatly appreciated.
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.Subject = "Your Newsletter Mailing Has Completed";
message.IsBodyHtml = true;
message.Body = "Total Emails Sent: " + emailSent +
"<br />Total Email Errors: " + emailError +
"<br />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.Subject = "Invalid Email Address";
message.IsBodyHtml = true;
message.Body = "An invalid email address has been found, please check the following " +
"email address:<br />" + 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.Subject = subject;
message.IsBodyHtml = true;
message.Body = "An Error Has Occurred: <br />Exception: <br />" + 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.Subject = subject;
message.IsBodyHtml = true;
message.Body = "An Error Has Occurred:<br /><br />" + body + "<br /><br />Exception: <br />" + ex.ToString();
smtpClient.Host = "";
smtpClient.Credentials = new System.Net.NetworkCredential("");
smtpClient.Send(message);
smtpClient.ServicePoint.CloseConnectionGroup(smtpClient.ServicePoint.ConnectionName);
}
}
}
}