Threading with an object and Session

  • Thread starter Gavin Lyons via .NET 247
  • Start date
G

Gavin Lyons via .NET 247

Hello,

I'm writing a newsletter application which uses backgroundthreading. I'm using Session variable to report on progresswhile it loops through a dataset. The 'Status.aspx' pagerefreshes every 5 seconds while outputing the Session variables.My problem is, once the page redirects to 'Status.aspx' its showthe that's it only gets half through the dataset. If I increaseThread.Sleep to 2000 goes all the way through. I don't get anyerror message, it's like the MailObj disappears once the pageredirects. Do I need to use something like Context.Items.Add ?

Any ideas would be great:)

Gavin Lyons




private void Send_Click(object sender,System.Web.UI.ImageClickEventArgs e)
{
if (Subject.Text!="")
{
string SQLString = "SELECT * FROM Members";
i386.Newsletter.mailer MailObj = new mailer();
MailObj.SMTPhost = "mail.smtp.com";
MailObj.From = From.SelectedValue;
MailObj.Body = Body();
MailObj.Sessions = true;
MailObj.EmailAddressField = "UserID";
MailObj.EmailNameField = "<!--FirstName--> <!--LastName-->";
MailObj.DataSet = i386.DatabaseSystem.GetDataSet(SQLString,"WebConfigDatabaseConnection");
MailObj.WebContext =(System.Web.HttpContext)Session["WebContext"];

Thread thread = new Thread(new ThreadStart(MailObj.Send));
thread.Priority = ThreadPriority.Lowest;
thread.Start();
Thread.Sleep(500);
Response.Redirect("status.aspx", true);

}
else
Label_Message.Text="Missing data!";


}



public class mailer
{
private string _SMTPhost="localhost";
private string _Body="";
private string _From="";
private string _FromName="";
private string _Subject="";
private string _DatabaseConnection;
private string _EmailAddressField;
private string _EmailNameField;
private System.Web.HttpContext _WebContext;
private DataSet _DataSet;
private bool _Sessions=true;
public string SMTPhost
{
get {return _SMTPhost;}
set {_SMTPhost=value;}
}
public string EmailNameField
{
get {return _EmailNameField;}
set {_EmailNameField=value;}
}
public string EmailAddressField
{
get {return _EmailAddressField;}
set {_EmailAddressField=value;}
}
public string Body
{
get {return _Body;}
set {_Body=value;}
}
public string Subject
{
get {return _Subject;}
set {_Subject=value;}
}
public string From
{
get {return _From;}
set {_From=value;}
}
public string FromName
{
get {return _FromName;}
set {_FromName=value;}
}
public bool Sessions
{
get {return _Sessions;}
set {_Sessions=value;}
}
public DataSet DataSet
{
set {_DataSet=value;}
get {return _DataSet;}
}
public System.Web.HttpContext WebContext
{
set {_WebContext=value;}
get {return _WebContext;}
}
private string ReplaceFields(DataRow DR, string String)
{
string ReplStr = String;
foreach (DataColumn Column in DR.Table.Columns)
{
ReplStr = ReplStr.Replace("<!--" + Column.ToString() + "-->",DR[Column.ToString()].ToString());
}
return ReplStr;
}
public void Send()
{
try
{
#region Initialise Sessions
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )//lock the session object
{
StringBuilder sb = new StringBuilder(); // for reporting

WebContext.Session["StatusLine"] = "Retrieving data tosend ..";
WebContext.Session["EmailReport"] = sb;
WebContext.Session["EmailCounter"] = "0";
WebContext.Session["TotalEmailsToSend"] =0;
WebContext.Session["Done"] = "false";
WebContext.Session["TotalEmailsToSend"] =this.DataSet.Tables[0].Rows.Count.ToString();
}
}
else
{
WebContext.Response.Write("Retrieving data to send ..");
}
#endregion
// Newsletter Merging
int startAt = Environment.TickCount;
int EmailCounter = 0;
bool TestMode = true;
foreach (DataRow DR in this.DataSet.Tables[0].Rows)
{
#region loop sending

// SMTP stmpobj = new SMTP(this.SMTPhost);
// EmailMessage emailmsg = new EmailMessage();

string BodyForEmail = ReplaceFields(DR, this.Body);
string ToForEmail = DR[this.EmailAddressField].ToString();
string ToNameForEmail = ReplaceFields(DR,this.EmailNameField);
string SubjectForEmail = ReplaceFields(DR, this.Subject);


if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )
{
WebContext.Session[ "StatusLine" ] = "Processing " +ToForEmail;
}
}
try
{
if (!TestMode)
{
//stmpobj.Send(emailmsg)
}
else
{

WebContext.Response.Write("Sending to "+ ToForEmail + "("+ ToNameForEmail + ") " + WebContext.Session[ "StatusLine"].ToString() + "<br/>");
}
if (this.Sessions)
{ // Reporting
((StringBuilder)WebContext.Session["EmailReport"]).Append(EmailCounter+ "," + DR["UserID"].ToString() +
", " + DateTime.Now.ToString() + ", Successful<BR>" );//Reporting
}
}
catch (Exception ErrorMsg)
{
if (this.Sessions)
{ // Reporting
((StringBuilder)WebContext.Session["EmailReport"]).Append(EmailCounter+ "," + DR["UserID"].ToString() +
", " + DateTime.Now.ToString() + ", Failed:" +ErrorMsg.Message + "<BR>" );
}
}
EmailCounter++;
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot)
WebContext.Session[ "EmailCounter" ] = EmailCounter;
}
#endregion
}
#region Sessions Final Values
if (this.Sessions)
{
lock( WebContext.Session.SyncRoot )
{
int ms = Environment.TickCount - startAt;
int seconds = ms/1000;
WebContext.Session[ "SecondsForMailMerge" ] =seconds.ToString();
WebContext.Session["Done"] = true;
WebContext.Session["StatusLine"] = "NewsletterCompleted!";
}
}
#endregion
// this.DataSet.Dispose();
}
catch (Exception ex)
{
#region Session Report with Error
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )
{
WebContext.Session["MailMergeException"] = ex;
}
}
#endregion
WebContext.Response.Write("Mailer Error:" + ex.Message);
}
}
}
 
D

David Browne

A background thread should not access the HttpContext or the Request. Both
of these are invalid once the page is done processing. Have the background
thread post the mail body directly to the session, or to some other global
scope. A subsequent request can then discover and use it.

David

Hello,

I'm writing a newsletter application which uses background threading. I'm
using Session variable to report on progress while it loops through a
dataset. The 'Status.aspx' page refreshes every 5 seconds while outputing
the Session variables. My problem is, once the page redirects to
'Status.aspx' its show the that's it only gets half through the dataset. If
I increase Thread.Sleep to 2000 goes all the way through. I don't get any
error message, it's like the MailObj disappears once the page redirects. Do
I need to use something like Context.Items.Add ?

Any ideas would be great:)

Gavin Lyons




private void Send_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
if (Subject.Text!="")
{
string SQLString = "SELECT * FROM Members";
i386.Newsletter.mailer MailObj = new mailer();
MailObj.SMTPhost = "mail.smtp.com";
MailObj.From = From.SelectedValue;
MailObj.Body = Body();
MailObj.Sessions = true;
MailObj.EmailAddressField = "UserID";
MailObj.EmailNameField = "<!--FirstName--> <!--LastName-->";
MailObj.DataSet = i386.DatabaseSystem.GetDataSet(SQLString,
"WebConfigDatabaseConnection");
MailObj.WebContext = (System.Web.HttpContext)Session["WebContext"];

Thread thread = new Thread(new ThreadStart(MailObj.Send));
thread.Priority = ThreadPriority.Lowest;
thread.Start();
Thread.Sleep(500);
Response.Redirect("status.aspx", true);

}
else
Label_Message.Text="Missing data!";


}



public class mailer
{
private string _SMTPhost="localhost";
private string _Body="";
private string _From="";
private string _FromName="";
private string _Subject="";
private string _DatabaseConnection;
private string _EmailAddressField;
private string _EmailNameField;
private System.Web.HttpContext _WebContext;
private DataSet _DataSet;
private bool _Sessions=true;
public string SMTPhost
{
get {return _SMTPhost;}
set {_SMTPhost=value;}
}
public string EmailNameField
{
get {return _EmailNameField;}
set {_EmailNameField=value;}
}
public string EmailAddressField
{
get {return _EmailAddressField;}
set {_EmailAddressField=value;}
}
public string Body
{
get {return _Body;}
set {_Body=value;}
}
public string Subject
{
get {return _Subject;}
set {_Subject=value;}
}
public string From
{
get {return _From;}
set {_From=value;}
}
public string FromName
{
get {return _FromName;}
set {_FromName=value;}
}
public bool Sessions
{
get {return _Sessions;}
set {_Sessions=value;}
}
public DataSet DataSet
{
set {_DataSet=value;}
get {return _DataSet;}
}
public System.Web.HttpContext WebContext
{
set {_WebContext=value;}
get {return _WebContext;}
}
private string ReplaceFields(DataRow DR, string String)
{
string ReplStr = String;
foreach (DataColumn Column in DR.Table.Columns)
{
ReplStr = ReplStr.Replace("<!--" + Column.ToString() + "-->",
DR[Column.ToString()].ToString());
}
return ReplStr;
}
public void Send()
{
try
{
#region Initialise Sessions
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )//lock the session object
{
StringBuilder sb = new StringBuilder(); // for reporting

WebContext.Session["StatusLine"] = "Retrieving data to send ..";
WebContext.Session["EmailReport"] = sb;
WebContext.Session["EmailCounter"] = "0";
WebContext.Session["TotalEmailsToSend"] =0;
WebContext.Session["Done"] = "false";
WebContext.Session["TotalEmailsToSend"] =
this.DataSet.Tables[0].Rows.Count.ToString();
}
}
else
{
WebContext.Response.Write("Retrieving data to send ..");
}
#endregion
// Newsletter Merging
int startAt = Environment.TickCount;
int EmailCounter = 0;
bool TestMode = true;
foreach (DataRow DR in this.DataSet.Tables[0].Rows)
{
#region loop sending

// SMTP stmpobj = new SMTP(this.SMTPhost);
// EmailMessage emailmsg = new EmailMessage();

string BodyForEmail = ReplaceFields(DR, this.Body);
string ToForEmail = DR[this.EmailAddressField].ToString();
string ToNameForEmail = ReplaceFields(DR, this.EmailNameField);
string SubjectForEmail = ReplaceFields(DR, this.Subject);


if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )
{
WebContext.Session[ "StatusLine" ] = "Processing " + ToForEmail;
}
}
try
{
if (!TestMode)
{
//stmpobj.Send(emailmsg)
}
else
{

WebContext.Response.Write("Sending to "+ ToForEmail + "(" + ToNameForEmail +
") " + WebContext.Session[ "StatusLine" ].ToString() + "<br/>");
}
if (this.Sessions)
{ // Reporting
((StringBuilder)WebContext.Session["EmailReport"]).Append(EmailCounter+ ","
+ DR["UserID"].ToString() +
", " + DateTime.Now.ToString() + ", Successful<BR>" );// Reporting
}
}
catch (Exception ErrorMsg)
{
if (this.Sessions)
{ // Reporting
((StringBuilder)WebContext.Session["EmailReport"]).Append(EmailCounter+ ","
+ DR["UserID"].ToString() +
", " + DateTime.Now.ToString() + ", Failed:" + ErrorMsg.Message + "<BR>" );
}
}
EmailCounter++;
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot)
WebContext.Session[ "EmailCounter" ] = EmailCounter;
}
#endregion
}
#region Sessions Final Values
if (this.Sessions)
{
lock( WebContext.Session.SyncRoot )
{
int ms = Environment.TickCount - startAt;
int seconds = ms/1000;
WebContext.Session[ "SecondsForMailMerge" ] = seconds.ToString();
WebContext.Session["Done"] = true;
WebContext.Session["StatusLine"] = "Newsletter Completed!";
}
}
#endregion
// this.DataSet.Dispose();
}
catch (Exception ex)
{
#region Session Report with Error
if (this.Sessions)
{
lock(WebContext.Session.SyncRoot )
{
WebContext.Session["MailMergeException"] = ex;
}
}
#endregion
WebContext.Response.Write("Mailer Error:" + ex.Message);
}
}
}
 
G

garethdjames

If you need to do the operation asyncronusly then take all the data of
the request and session, populate an object then put this object on a
message queue

Have another application read messages of the queue and process them
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top