By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,369 Members | 1,207 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,369 IT Pros & Developers. It's quick & easy.

threading and session object

P: n/a
Hello

I am starting a new thread in a button click event.

This thread calls an method which sends emails, I don't want the page
to wait for the emails to finish going out as it slows the user down.

I have to set a session to null in the same click method but when
I do this I get this funny error.

"An unhandled exception of type
'System.Runtime.Serialization.SerializationExcepti on' occurred in
Unknown Module.

Additional information: The type System.Web.HttpException in Assembly
System.Web, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a is not marked as serializable."

Here is a rough example of the code. There is no difference if I move
the Session=null
statement before or after the thread, or if I move the email code into
a separate class.

private void MultipleAttachEmail_Click(object sender, System.EventArgs
e)
{
ThreadStart ts = new ThreadStart(multipleMail);
Thread thread = new Thread(ts);
thread.Start();
Session["BasketSession"] = null;
Response.Redirect("DocBasketCheckout.aspx?%^="+Ema ilAddress.Text);
}

private void multipleMail ()
{
MailMessage msgMail = new MailMessage();
msgMail.To = EmailAddress.Text;
msgMail.From = "we*****@crash.com";
msgMail.Subject = "Document Basket Contents";
msgMail.BodyFormat = MailFormat.Text;
msgMail.Body = " ";

// Gets document location path from Document Basket.
foreach(DataGridItem dgi in documentDataGrid.Items)
{
string dLink = baseURL + dgi.Cells[2].Text;
msgMail.Attachments.Add(new MailAttachment(Server.MapPath( dLink
)));
}
SmtpMail.SmtpServer = "127.0.0.1";
SmtpMail.Send(msgMail);
}
Nov 18 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Hi Matt,

This is not directly addressing your question, but I think it might very
well be related.

You'll want to be real careful with threads in this scenario. I think the
failure you're seeing might have nothing to do with clearing the session but
something that's failing inside that thread method (for example the DataGrid
access).

The problem here is that when you fire off a new thread and you point it at
the method in question the class that it belongs to or some of hte
components on it might no longer be there because the page and the class
that goes with it has terminated already. One thing you can do work around
this is a use a static method.

In your scenario I would probably build the message on the ASP.Net thread
(because it relies on some data from the page) and fire only the sending on
the new thread and stick that into a generic static method. IOW, minimize
the reliance of the thread method on anything from the main ASP.Net page
which may be terminated/ing when the thread executes.

+++ Rick ---

--

Rick Strahl
West Wind Technologies
http://www.west-wind.com/
http://www.west-wind.com/weblog/
----------------------------------
Making waves on the Web
"MattB" <MB*********@yahoo.co.uk> wrote in message
news:b4**************************@posting.google.c om...
Hello

I am starting a new thread in a button click event.

This thread calls an method which sends emails, I don't want the page
to wait for the emails to finish going out as it slows the user down.

I have to set a session to null in the same click method but when
I do this I get this funny error.

"An unhandled exception of type
'System.Runtime.Serialization.SerializationExcepti on' occurred in
Unknown Module.

Additional information: The type System.Web.HttpException in Assembly
System.Web, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a is not marked as serializable."

Here is a rough example of the code. There is no difference if I move
the Session=null
statement before or after the thread, or if I move the email code into
a separate class.

private void MultipleAttachEmail_Click(object sender, System.EventArgs
e)
{
ThreadStart ts = new ThreadStart(multipleMail);
Thread thread = new Thread(ts);
thread.Start();
Session["BasketSession"] = null;
Response.Redirect("DocBasketCheckout.aspx?%^="+Ema ilAddress.Text);
}

private void multipleMail ()
{
MailMessage msgMail = new MailMessage();
msgMail.To = EmailAddress.Text;
msgMail.From = "we*****@crash.com";
msgMail.Subject = "Document Basket Contents";
msgMail.BodyFormat = MailFormat.Text;
msgMail.Body = " ";

// Gets document location path from Document Basket.
foreach(DataGridItem dgi in documentDataGrid.Items)
{
string dLink = baseURL + dgi.Cells[2].Text;
msgMail.Attachments.Add(new MailAttachment(Server.MapPath( dLink
)));
}
SmtpMail.SmtpServer = "127.0.0.1";
SmtpMail.Send(msgMail);
}

Nov 18 '05 #2

P: n/a
Another possible way, is to store all data relevant to the thread operation,
in a value type, and pass it by value to the method.
Thus copying the relevant data.
Sharon.
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
Hi Matt,

This is not directly addressing your question, but I think it might very
well be related.

You'll want to be real careful with threads in this scenario. I think the
failure you're seeing might have nothing to do with clearing the session but something that's failing inside that thread method (for example the DataGrid access).

The problem here is that when you fire off a new thread and you point it at the method in question the class that it belongs to or some of hte
components on it might no longer be there because the page and the class
that goes with it has terminated already. One thing you can do work around
this is a use a static method.

In your scenario I would probably build the message on the ASP.Net thread
(because it relies on some data from the page) and fire only the sending on the new thread and stick that into a generic static method. IOW, minimize
the reliance of the thread method on anything from the main ASP.Net page
which may be terminated/ing when the thread executes.

+++ Rick ---

--

Rick Strahl
West Wind Technologies
http://www.west-wind.com/
http://www.west-wind.com/weblog/
----------------------------------
Making waves on the Web
"MattB" <MB*********@yahoo.co.uk> wrote in message
news:b4**************************@posting.google.c om...
Hello

I am starting a new thread in a button click event.

This thread calls an method which sends emails, I don't want the page
to wait for the emails to finish going out as it slows the user down.

I have to set a session to null in the same click method but when
I do this I get this funny error.

"An unhandled exception of type
'System.Runtime.Serialization.SerializationExcepti on' occurred in
Unknown Module.

Additional information: The type System.Web.HttpException in Assembly
System.Web, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a is not marked as serializable."

Here is a rough example of the code. There is no difference if I move
the Session=null
statement before or after the thread, or if I move the email code into
a separate class.

private void MultipleAttachEmail_Click(object sender, System.EventArgs
e)
{
ThreadStart ts = new ThreadStart(multipleMail);
Thread thread = new Thread(ts);
thread.Start();
Session["BasketSession"] = null;
Response.Redirect("DocBasketCheckout.aspx?%^="+Ema ilAddress.Text);
}

private void multipleMail ()
{
MailMessage msgMail = new MailMessage();
msgMail.To = EmailAddress.Text;
msgMail.From = "we*****@crash.com";
msgMail.Subject = "Document Basket Contents";
msgMail.BodyFormat = MailFormat.Text;
msgMail.Body = " ";

// Gets document location path from Document Basket.
foreach(DataGridItem dgi in documentDataGrid.Items)
{
string dLink = baseURL + dgi.Cells[2].Text;
msgMail.Attachments.Add(new MailAttachment(Server.MapPath( dLink
)));
}
SmtpMail.SmtpServer = "127.0.0.1";
SmtpMail.Send(msgMail);
}


Nov 18 '05 #3

P: n/a
Not exactly. The error here is that this line

// Gets document location path from Document Basket.
foreach(DataGridItem dgi in documentDataGrid.Items)

is contained inside the thread code. and it operates on the datagrid. the
datagrid is owned by the main thread. A child thread cannot touch a main
thread's object in a thread safe manner. If this were a winforms
application, the fix would imply calling control.Invoke. Sadly, this is not
available in the webforms architecture. Typically, this call will work about
40 - 50 percent of the time on a NT architecture and even higher on pre NT
architectures, but it is still wrong and rightly avoided. The work around is
to not manipulate the datagrid inside the thread. A more sophisticated
technique of passing in the reference to the datagrid to the thread exists
but it isn't exactly warranted here.

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/27cok
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
Hi Matt,

This is not directly addressing your question, but I think it might very
well be related.

You'll want to be real careful with threads in this scenario. I think the
failure you're seeing might have nothing to do with clearing the session
but
something that's failing inside that thread method (for example the
DataGrid
access).

The problem here is that when you fire off a new thread and you point it
at
the method in question the class that it belongs to or some of hte
components on it might no longer be there because the page and the class
that goes with it has terminated already. One thing you can do work around
this is a use a static method.

In your scenario I would probably build the message on the ASP.Net thread
(because it relies on some data from the page) and fire only the sending
on
the new thread and stick that into a generic static method. IOW, minimize
the reliance of the thread method on anything from the main ASP.Net page
which may be terminated/ing when the thread executes.

+++ Rick ---

--

Rick Strahl
West Wind Technologies
http://www.west-wind.com/
http://www.west-wind.com/weblog/
----------------------------------
Making waves on the Web
"MattB" <MB*********@yahoo.co.uk> wrote in message
news:b4**************************@posting.google.c om...
Hello

I am starting a new thread in a button click event.

This thread calls an method which sends emails, I don't want the page
to wait for the emails to finish going out as it slows the user down.

I have to set a session to null in the same click method but when
I do this I get this funny error.

"An unhandled exception of type
'System.Runtime.Serialization.SerializationExcepti on' occurred in
Unknown Module.

Additional information: The type System.Web.HttpException in Assembly
System.Web, Version=1.0.5000.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a is not marked as serializable."

Here is a rough example of the code. There is no difference if I move
the Session=null
statement before or after the thread, or if I move the email code into
a separate class.

private void MultipleAttachEmail_Click(object sender, System.EventArgs
e)
{
ThreadStart ts = new ThreadStart(multipleMail);
Thread thread = new Thread(ts);
thread.Start();
Session["BasketSession"] = null;
Response.Redirect("DocBasketCheckout.aspx?%^="+Ema ilAddress.Text);
}

private void multipleMail ()
{
MailMessage msgMail = new MailMessage();
msgMail.To = EmailAddress.Text;
msgMail.From = "we*****@crash.com";
msgMail.Subject = "Document Basket Contents";
msgMail.BodyFormat = MailFormat.Text;
msgMail.Body = " ";

// Gets document location path from Document Basket.
foreach(DataGridItem dgi in documentDataGrid.Items)
{
string dLink = baseURL + dgi.Cells[2].Text;
msgMail.Attachments.Add(new MailAttachment(Server.MapPath( dLink
)));
}
SmtpMail.SmtpServer = "127.0.0.1";
SmtpMail.Send(msgMail);
}


Nov 18 '05 #4

P: n/a
Hi Alvin,

You're right of course and that's sort of what I was getting at <g>...

In this case though I'm certain that the problem is that hte page is gone by
the time the thread fires up. Matt does a Redirect() immediately following
the Thread creation which exits the page and recylces the thread. This is
likely to happen way before the new thread even starts. So if there's any
reliance on anything from the ASP page it's not likely to be there.

I've run into this in a few of my own applications and it's really a bitch
to catch if you don't know this is happening because in most cases you don't
get a failure in teh ASP.Net page because *it* completed fine. The exception
happens on another thread unknown to the ASP.Net runtime and thus you get no
messages. The thread falls down and goes away and you get an eventlog entry
for this, but otherwise nothing.

In general I would say this is a bad idea unless you always force your state
to the thread object itself and/or you call fully selfcontained static code.

Another possibly better alternative is to use Asynchronous Requests...

+++ Rick ---
Nov 18 '05 #5

P: n/a
maybe this way will work:

aspx page
=========
<%@ Page Language="cs" %>
<%@ import namespace="System.Threading" %>
<%@ import namespace="test" %>

<%
string[] passArr = new string[2]{"arr val 1", "arr val 2"};

ThreadProc tp = new ThreadProc(passArr);
Thread t = new Thread(new ThreadStart(tp.ThreadProcStart));
t.Start();
%>
<html>
<head>
</head>
<body>
</body>
</html>

thread class
==========
using System.Threading;
using System.IO;

namespace test
{
public class ThreadProc
{
private string[] m_dispStrArr;

public ThreadProc(string[] inStrArr) {
m_dispStrArr = inStrArr;
}

public void ThreadProcStart() {
for (int i = 0; i < 20; i++)
{
StreamWriter fsw =
File.AppendText(System.AppDomain.CurrentDomain.Bas eDirectory + "\\log.txt");
fsw.WriteLine("m_dispStr: " + m_dispStrArr[0] + " " + m_dispStrArr[1]
+ " i: " + i);
fsw.Close();
fsw = null;

Thread.Sleep(1000);
}
}
}
}

it works but, maybe you can find a flaw?
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2***************@tk2msftngp13.phx.gbl...
Hi Alvin,

You're right of course and that's sort of what I was getting at <g>...

In this case though I'm certain that the problem is that hte page is gone by the time the thread fires up. Matt does a Redirect() immediately following
the Thread creation which exits the page and recylces the thread. This is
likely to happen way before the new thread even starts. So if there's any
reliance on anything from the ASP page it's not likely to be there.

I've run into this in a few of my own applications and it's really a bitch
to catch if you don't know this is happening because in most cases you don't get a failure in teh ASP.Net page because *it* completed fine. The exception happens on another thread unknown to the ASP.Net runtime and thus you get no messages. The thread falls down and goes away and you get an eventlog entry for this, but otherwise nothing.

In general I would say this is a bad idea unless you always force your state to the thread object itself and/or you call fully selfcontained static code.
Another possibly better alternative is to use Asynchronous Requests...

+++ Rick ---

Nov 18 '05 #6

P: n/a
well as rick pointed out, the other issue is that by the time the thread is
finished, the page is gone. I've seen others put a sleep in the main page or
a join to force the main thread to wait on the child thread to execute.
Infact, i've used the join which seems to work well.

Even in OP's case, the thread is still touching the response object which is
a main thread object.

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/27cok
"Sharon" <ta*******@hotmail.com> wrote in message
news:eC**************@TK2MSFTNGP10.phx.gbl...
maybe this way will work:

aspx page
=========
<%@ Page Language="cs" %>
<%@ import namespace="System.Threading" %>
<%@ import namespace="test" %>

<%
string[] passArr = new string[2]{"arr val 1", "arr val 2"};

ThreadProc tp = new ThreadProc(passArr);
Thread t = new Thread(new ThreadStart(tp.ThreadProcStart));
t.Start();
%>
<html>
<head>
</head>
<body>
</body>
</html>

thread class
==========
using System.Threading;
using System.IO;

namespace test
{
public class ThreadProc
{
private string[] m_dispStrArr;

public ThreadProc(string[] inStrArr) {
m_dispStrArr = inStrArr;
}

public void ThreadProcStart() {
for (int i = 0; i < 20; i++)
{
StreamWriter fsw =
File.AppendText(System.AppDomain.CurrentDomain.Bas eDirectory +
"\\log.txt");
fsw.WriteLine("m_dispStr: " + m_dispStrArr[0] + " " + m_dispStrArr[1]
+ " i: " + i);
fsw.Close();
fsw = null;

Thread.Sleep(1000);
}
}
}
}

it works but, maybe you can find a flaw?
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2***************@tk2msftngp13.phx.gbl...
Hi Alvin,

You're right of course and that's sort of what I was getting at <g>...

In this case though I'm certain that the problem is that hte page is gone

by
the time the thread fires up. Matt does a Redirect() immediately
following
the Thread creation which exits the page and recylces the thread. This is
likely to happen way before the new thread even starts. So if there's any
reliance on anything from the ASP page it's not likely to be there.

I've run into this in a few of my own applications and it's really a
bitch
to catch if you don't know this is happening because in most cases you

don't
get a failure in teh ASP.Net page because *it* completed fine. The

exception
happens on another thread unknown to the ASP.Net runtime and thus you get

no
messages. The thread falls down and goes away and you get an eventlog

entry
for this, but otherwise nothing.

In general I would say this is a bad idea unless you always force your

state
to the thread object itself and/or you call fully selfcontained static

code.

Another possibly better alternative is to use Asynchronous Requests...

+++ Rick ---


Nov 18 '05 #7

P: n/a
Thanks for all the feedback.

Decoupling - I guess thats the word for it - the datagrid from the
main thread and filling a separate string array or arraylist to pass
to a separate email class did the trick. I cannot wait in my asp.net
page codebehind to wait for a thread.join. My only remaining query is
there anything I should do in the separate email class to close the
thread, I assume garbage collection will take care of this
anyhow....Also maybe I could start the thread in the separate email
class..

here is current code sample...

private void MultipleAttachEmail_Click(object sender, System.EventArgs
e)
{
foreach(DataGridItem dgi in documentDataGrid.Items)
{
attachments.Add(Server.MapPath(baseURL + dgi.Cells[2].Text));
}
DocumentsEmail dem = new
DocumentsEmail(attachments,EmailAddress.Text);
ThreadStart ts = new ThreadStart(dem.SendMultipleAttachEmail);
thread = new System.Threading.Thread(ts);
thread.Start();
Session["BasketSession"] = null;
Response.Redirect("DocBasketCheckout.aspx?%^="+Ema ilAddress.Text);
}

the new DocumentsEmail class

using System;
using System.Collections;
using System.Threading;
using System.Web.Mail;
using System.Web;

namespace Org.Web.UI
{
public class DocumentsEmail
{
private ArrayList _intArrList;
private string _email;

public DocumentsEmail(ArrayList inArrList, string inEmail)
{
_intArrList = inArrList;
_email = inEmail;
}

public void SendMultipleAttachEmail()
{
MailMessage msgMail = new MailMessage();
msgMail.To = _email;
msgMail.From = "Org Website" + " <we*****@org.co.uk>";
msgMail.Subject = "Your Documents";
msgMail.BodyFormat = MailFormat.Text;
msgMail.Body = " ";

// Gets document location path from Document Basket.
foreach(string dgi in _intArrList)
{
msgMail.Attachments.Add(new MailAttachment(dgi));
}

SmtpMail.SmtpServer = "192.168.0.253";
SmtpMail.Send(msgMail);
}
}

"Alvin Bruney [MVP]" <vapor at steaming post office> wrote in message news:<#z**************@TK2MSFTNGP12.phx.gbl>...
well as rick pointed out, the other issue is that by the time the thread is
finished, the page is gone. I've seen others put a sleep in the main page or
a join to force the main thread to wait on the child thread to execute.
Infact, i've used the join which seems to work well.

Even in OP's case, the thread is still touching the response object which is
a main thread object.

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/27cok
"Sharon" <ta*******@hotmail.com> wrote in message
news:eC**************@TK2MSFTNGP10.phx.gbl...
maybe this way will work:

aspx page
=========
<%@ Page Language="cs" %>
<%@ import namespace="System.Threading" %>
<%@ import namespace="test" %>

<%
string[] passArr = new string[2]{"arr val 1", "arr val 2"};

ThreadProc tp = new ThreadProc(passArr);
Thread t = new Thread(new ThreadStart(tp.ThreadProcStart));
t.Start();
%>
<html>
<head>
</head>
<body>
</body>
</html>

thread class
==========
using System.Threading;
using System.IO;

namespace test
{
public class ThreadProc
{
private string[] m_dispStrArr;

public ThreadProc(string[] inStrArr) {
m_dispStrArr = inStrArr;
}

public void ThreadProcStart() {
for (int i = 0; i < 20; i++)
{
StreamWriter fsw =
File.AppendText(System.AppDomain.CurrentDomain.Bas eDirectory +
"\\log.txt");
fsw.WriteLine("m_dispStr: " + m_dispStrArr[0] + " " + m_dispStrArr[1]
+ " i: " + i);
fsw.Close();
fsw = null;

Thread.Sleep(1000);
}
}
}
}

it works but, maybe you can find a flaw?
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2***************@tk2msftngp13.phx.gbl...
Hi Alvin,

You're right of course and that's sort of what I was getting at <g>...

In this case though I'm certain that the problem is that hte page is gone by the time the thread fires up. Matt does a Redirect() immediately
following
the Thread creation which exits the page and recylces the thread. This is
likely to happen way before the new thread even starts. So if there's any
reliance on anything from the ASP page it's not likely to be there.

I've run into this in a few of my own applications and it's really a
bitch
to catch if you don't know this is happening because in most cases you don't get a failure in teh ASP.Net page because *it* completed fine. The exception happens on another thread unknown to the ASP.Net runtime and thus you get no messages. The thread falls down and goes away and you get an eventlog entry for this, but otherwise nothing.

In general I would say this is a bad idea unless you always force your state to the thread object itself and/or you call fully selfcontained static code.
Another possibly better alternative is to use Asynchronous Requests...

+++ Rick ---


Nov 18 '05 #8

P: n/a
i think a separate class will work because the aspx instance
is holding reference to the array, and is passing that reference to the
class.
when the aspx is gone, the reference will no longer exist,
but the array data in the heap will still exist because the thread class is
still holding
reference to it.
when the thread class finishes execution, the array data will be collected.
true?

"Alvin Bruney [MVP]" <vapor at steaming post office> wrote in message
news:%2****************@TK2MSFTNGP12.phx.gbl...
well as rick pointed out, the other issue is that by the time the thread is finished, the page is gone. I've seen others put a sleep in the main page or a join to force the main thread to wait on the child thread to execute.
Infact, i've used the join which seems to work well.

Even in OP's case, the thread is still touching the response object which is a main thread object.

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/27cok
"Sharon" <ta*******@hotmail.com> wrote in message
news:eC**************@TK2MSFTNGP10.phx.gbl...
maybe this way will work:

aspx page
=========
<%@ Page Language="cs" %>
<%@ import namespace="System.Threading" %>
<%@ import namespace="test" %>

<%
string[] passArr = new string[2]{"arr val 1", "arr val 2"};

ThreadProc tp = new ThreadProc(passArr);
Thread t = new Thread(new ThreadStart(tp.ThreadProcStart));
t.Start();
%>
<html>
<head>
</head>
<body>
</body>
</html>

thread class
==========
using System.Threading;
using System.IO;

namespace test
{
public class ThreadProc
{
private string[] m_dispStrArr;

public ThreadProc(string[] inStrArr) {
m_dispStrArr = inStrArr;
}

public void ThreadProcStart() {
for (int i = 0; i < 20; i++)
{
StreamWriter fsw =
File.AppendText(System.AppDomain.CurrentDomain.Bas eDirectory +
"\\log.txt");
fsw.WriteLine("m_dispStr: " + m_dispStrArr[0] + " " + m_dispStrArr[1] + " i: " + i);
fsw.Close();
fsw = null;

Thread.Sleep(1000);
}
}
}
}

it works but, maybe you can find a flaw?
"Rick Strahl [MVP]" <ri********@hotmail.com> wrote in message
news:%2***************@tk2msftngp13.phx.gbl...
Hi Alvin,

You're right of course and that's sort of what I was getting at <g>...

In this case though I'm certain that the problem is that hte page is gone
by
the time the thread fires up. Matt does a Redirect() immediately
following
the Thread creation which exits the page and recylces the thread. This
is likely to happen way before the new thread even starts. So if there's any reliance on anything from the ASP page it's not likely to be there.

I've run into this in a few of my own applications and it's really a
bitch
to catch if you don't know this is happening because in most cases you

don't
get a failure in teh ASP.Net page because *it* completed fine. The

exception
happens on another thread unknown to the ASP.Net runtime and thus you

get no
messages. The thread falls down and goes away and you get an eventlog

entry
for this, but otherwise nothing.

In general I would say this is a bad idea unless you always force your

state
to the thread object itself and/or you call fully selfcontained static

code.

Another possibly better alternative is to use Asynchronous Requests...

+++ Rick ---



Nov 18 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.