473,396 Members | 1,871 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Basic Mutlithreading Questions

JJ
I've done a little multi-threading on winform apps some time ago now, so I'm
not a complete beginner, but best assume I am for any explanations..:

This is an asp.net 2.0 website, using c#:
I have a thread whose job is to send several emails (i.e. a long task that
mustn't be run by more that one user at a time).
It all works fine, but I am concerned about the lifetime of a thread in the
case of smtp errors, and how it will work with several users trying to run
the same process.

The thread is started like:
ParameterizedThreadStart pts = new ParameterizedThreadStart(SendEmails);
Thread thread = new Thread(pts);
thread.Name = "SendEmails";
thread.Priority = ThreadPriority.BelowNormal;
thread.Start(parameters);

Several static variables are written to by the main calling code (the main
app) and then by the 'SendEmails' thread, in the following manner:

Lock.AcquireWriterLock(Timeout.Infinite);
Email.SentMails = 0;
Email.IsSending = true;
Lock.ReleaseWriterLock();

I am therefore assuming that if another user is viewing the pages and tries
to run the email sending process, I can check to see if the Email.IsSending
is set and if it is, don't allow the 'SendEmails' thread to be run and
present a 'busy' page. Does this sound correct?

My questions are:
1. If there are some unexpected errors in the SendEmails thread, would the
thread ever end? Should threads always be started with some sort of
timeout - of so how ? Should the thread's code always be in some sort of
try..catch ?

2. To do actions on the database only when the thread finishes, (i.e. using
Thread.Wait()), I assume I have to start a main calling thread first, which
itself will wait for the SendEmails thread to finish before it does its job?

3. How can you check if a particular thread is running, whichever user it
was started by, so I don't accidentally try to start another one? (is my
approach with setting a static flag for a particular thread - in this case
'IsSending' - the best approach?

4. If I was to have a 'Cancel Sending' button, is there any cleaning up or
waiting I need to do (apart from resetting Email.IsSending = false), or is
it just simply Thread.Abort?

Sorry for the numerous questions,

JJ
May 20 '07 #1
3 1496
Hi JJ,

My questions are:
1. If there are some unexpected errors in the SendEmails thread, would the
thread ever end? Should threads always be started with some sort of
timeout - of so how ? Should the thread's code always be in some sort of
try..catch ?
Yes. The Exception will kill the thread. Your best bet is to ensure that
that doesn't happen by wrapping your mainline code into exception handlers.

2. To do actions on the database only when the thread finishes, (i.e.
using Thread.Wait()), I assume I have to start a main calling thread
first, which itself will wait for the SendEmails thread to finish before
it does its job?
Look into using WaitHandles (AutoResetEvent works great for this). Basically
you can use these WaitHandles to make a thread wait until another thread
triggers it.

I recently posted a blog entry about creating a basic Scheduler in ASP.NET
here and it demonstrates how you can do this:
http://west-wind.com/weblog/posts/67557.aspx

The code's not quite generic, but close and might give you an idea how you
can run a 'background' thread in ASP.NET whether you're launching it on app
start (as the post does) or whether you explicitly launch it from a specific
page hit.
3. How can you check if a particular thread is running, whichever user it
was started by, so I don't accidentally try to start another one? (is my
approach with setting a static flag for a particular thread - in this case
'IsSending' - the best approach?
You can't easily do that at least not reliably. Your best bet is to create a
scheduler that runs - does what it needs to and goes to sleep until the next
request is submitted.

4. If I was to have a 'Cancel Sending' button, is there any cleaning up or
waiting I need to do (apart from resetting Email.IsSending = false), or is
it just simply Thread.Abort?
Typically you shouldn't call Thread.Abort() as it is a hard reset and
doesn't clean up resources. A better approach for you is probably to check
on every iteration (ie. after each email that's been sent) if the thread
should be cancelled and then simply exit the loop and or method you're
running in.

+++ Rick ---

--

Rick Strahl
West Wind Technologies
www.west-wind.com/weblog

May 21 '07 #2
JJ
Hi Rick,

Thanks for you information and a great article. I do have some other
questions based on the info though:

Thanks for clearing up the 'Cancel thread' bit - setting a flag and exiting
the loop is a lot cleaner.

My confusion seems to be around two areas (in comparison with winform apps):
1. What the scope of threads are when it comes to different users accessing
the website;
[ i.e. are the main website pages/classes all running on ONE thread and
being accessed by multiple users, or does each user that accesses the
website start a new separate thread on the webserver?]
2. The effect of waiting for a thread to complete, based on the above
confusion;
[i.e. does the whole website freeze if the main calling code waits for a
thread to complete? Does it freeze for just the user that started the
'SendEmails' thread or for the entire website for all users?]

My concern also is not so much keeping the 'SendEmails' thread alive, as
much as making sure I don't keep spawning new threads or keeping the thread
alive indefinately because of no timeout and some sort of sending hangup on
the smtp server. Clearly I can't restart a shared web server, like I could
just exit a winform app and all its spawned threads.

Your example has a thread running indefintately - there are reasons why I
don't want to do this - one being that this is only one small function of
the website that may not always be used, so it seems in appropriate to keep
the thread running, and more appropriate to only run it when it is needed.

If I was to use a WaitHandle, which looks similar to the Thread.Wait
approach, in order to have some sort of failsafe timeout and to only update
data when the 'SendEmails' thread has done its job, wouldn't I still need to
do this waiting in new a calling thread (the 'MainSendEmailsThread' thread
that in turn calls the 'SendEmails' thread )?

My thinking being that I wouldn't want the main code to stop and wait -
doesn't this stop other users accessing that class (or the website) too (see
my 'confusion' explanation above)? Having a 'MainSendEmailsThread' and a
'SendEmailsThread' would mean that the 'MainSendEmailsThread' would just set
the 'IsSending' flag then call the 'SendEmailsThread' and wait for its
completion, before doing any tidying up or data updating. That is, the
thread that is 'frozen' whilst waiting is the 'MainSendEmailsThread'
and not the main website code, hence allowing that user and others to
continue viewing pages whilst the two threads are running.

In effect, both threads would only have one instance running as a check
would be made each time a user clicks the 'Send Emails' button to see if the
'IsSending' flag is set. If it is, then the user would be informed the the
function is 'busy', and no threads would be started by that user.

Is this all based on entirely the wrong assumption about asp.net threads, or
am I on the right approach for this senario?

Thanks in advance,

JJ
"Rick Strahl [MVP]" <ri********@hotmail.comwrote in message
news:81**********************************@microsof t.com...
Hi JJ,

>My questions are:
1. If there are some unexpected errors in the SendEmails thread, would
the thread ever end? Should threads always be started with some sort of
timeout - of so how ? Should the thread's code always be in some sort of
try..catch ?

Yes. The Exception will kill the thread. Your best bet is to ensure that
that doesn't happen by wrapping your mainline code into exception
handlers.

>2. To do actions on the database only when the thread finishes, (i.e.
using Thread.Wait()), I assume I have to start a main calling thread
first, which itself will wait for the SendEmails thread to finish before
it does its job?

Look into using WaitHandles (AutoResetEvent works great for this).
Basically you can use these WaitHandles to make a thread wait until
another thread triggers it.

I recently posted a blog entry about creating a basic Scheduler in ASP.NET
here and it demonstrates how you can do this:
http://west-wind.com/weblog/posts/67557.aspx

The code's not quite generic, but close and might give you an idea how you
can run a 'background' thread in ASP.NET whether you're launching it on
app start (as the post does) or whether you explicitly launch it from a
specific page hit.
>3. How can you check if a particular thread is running, whichever user it
was started by, so I don't accidentally try to start another one? (is my
approach with setting a static flag for a particular thread - in this
case 'IsSending' - the best approach?

You can't easily do that at least not reliably. Your best bet is to create
a scheduler that runs - does what it needs to and goes to sleep until the
next request is submitted.

>4. If I was to have a 'Cancel Sending' button, is there any cleaning up
or waiting I need to do (apart from resetting Email.IsSending = false),
or is it just simply Thread.Abort?

Typically you shouldn't call Thread.Abort() as it is a hard reset and
doesn't clean up resources. A better approach for you is probably to check
on every iteration (ie. after each email that's been sent) if the thread
should be cancelled and then simply exit the loop and or method you're
running in.

+++ Rick ---

--

Rick Strahl
West Wind Technologies
www.west-wind.com/weblog

May 21 '07 #3
I have a thread whose job is to send several emails (i.e. a long task that
mustn't be run by more that one user at a time).
It all works fine, but I am concerned about the lifetime of a thread in
the case of smtp errors, and how it will work with several users trying to
run the same process.
Email servers are async in nature, you are forcing a queue mechanism. This
is bad, very bad.
Another thing, did I mention that this was bad?
Several static variables are written to by the main calling code (the main
app) and then by the 'SendEmails' thread, in the following manner:
Bad. very bad. Your main application will essential block your calling
threads with the writer lock. If the writer lock chokes, you don't have an
exception block, your application will hang. Even if it doesn't hang, it
will slow to a crawl as load increases.

Additionally, you sit and wait for a lock for how ever long it takes. Let's
say it takes 23 minutes to acquire that lock, your user is sitting there for
23 minutes looking at a busy page. So they close the browser and come back
in again, the lock is still there. But now, two requests are waiting on a
lock. Lock set to infinite time out - bad idea.

1. If there are some unexpected errors in the SendEmails thread, would the
thread ever end? Should threads always be started with some sort of
timeout - of so how ? Should the thread's code always be in some sort of
try..catch ?

I think you know the answers to those questions.

2. To do actions on the database only when the thread finishes, (i.e. using
Thread.Wait()), I assume I have to start a main calling thread first, which
itself will wait for the SendEmails thread to finish before it does its job?

No, you can synchronize the threads which will essential mirror a wait
behavior. There are some wait states that are more efficient than others so
you may want to look at those. However, this is the least of your problems.

3. How can you check if a particular thread is running, whichever user it
was started by, so I don't accidentally try to start another one? (is my
approach with setting a static flag for a particular thread - in this case
'IsSending' - the best approach?

No. When you start a thread, don't throw away the handle to the thread. Keep
it, so you can use it to inquire about the state of the thread. In that
case, it is variable thread.IsRunning (if memory serves me correctly)

4. If I was to have a 'Cancel Sending' button, is there any cleaning up or
waiting I need to do (apart from resetting Email.IsSending = false), or is
it just simply Thread.Abort?

Here is the thing with thread.abort. Say you have a moving car and you want
to bring it to a halt, you can drive it into a brick wall to stop it, or you
can use the brake pedal. Both get the job done, one does so more *elegantly
than the other. Use a flag to signal your thread to stop.

--
Regards,
Alvin Bruney
------------------------------------------------------
Shameless author plug
Excel Services for .NET is coming...
https://www.microsoft.com/MSPress/books/10933.aspx
OWC Black Book www.lulu.com/owc
Professional VSTO 2005 - Wrox/Wiley
"JJ" <ab*@xyz.comwrote in message
news:ey**************@TK2MSFTNGP04.phx.gbl...
I've done a little multi-threading on winform apps some time ago now, so
I'm not a complete beginner, but best assume I am for any explanations..:

This is an asp.net 2.0 website, using c#:
I have a thread whose job is to send several emails (i.e. a long task that
mustn't be run by more that one user at a time).
It all works fine, but I am concerned about the lifetime of a thread in
the case of smtp errors, and how it will work with several users trying to
run the same process.

The thread is started like:
ParameterizedThreadStart pts = new ParameterizedThreadStart(SendEmails);
Thread thread = new Thread(pts);
thread.Name = "SendEmails";
thread.Priority = ThreadPriority.BelowNormal;
thread.Start(parameters);

Several static variables are written to by the main calling code (the main
app) and then by the 'SendEmails' thread, in the following manner:

Lock.AcquireWriterLock(Timeout.Infinite);
Email.SentMails = 0;
Email.IsSending = true;
Lock.ReleaseWriterLock();

I am therefore assuming that if another user is viewing the pages and
tries to run the email sending process, I can check to see if the
Email.IsSending is set and if it is, don't allow the 'SendEmails' thread
to be run and present a 'busy' page. Does this sound correct?

My questions are:
1. If there are some unexpected errors in the SendEmails thread, would the
thread ever end? Should threads always be started with some sort of
timeout - of so how ? Should the thread's code always be in some sort of
try..catch ?

2. To do actions on the database only when the thread finishes, (i.e.
using Thread.Wait()), I assume I have to start a main calling thread
first, which itself will wait for the SendEmails thread to finish before
it does its job?

3. How can you check if a particular thread is running, whichever user it
was started by, so I don't accidentally try to start another one? (is my
approach with setting a static flag for a particular thread - in this case
'IsSending' - the best approach?

4. If I was to have a 'Cancel Sending' button, is there any cleaning up or
waiting I need to do (apart from resetting Email.IsSending = false), or is
it just simply Thread.Abort?

Sorry for the numerous questions,

JJ

May 23 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: AK | last post by:
I don't want any part of the previous discussion on Visual Basic versus Visual Basic.Net. My query is about using Visual Basic for Applications; and whether it is better to use Visual Basic 6 or...
7
by: Michael Foord | last post by:
#!/usr/bin/python -u # 15-09-04 # v1.0.0 # auth_example.py # A simple script manually demonstrating basic authentication. # Copyright Michael Foord # Free to use, modify and relicense. #...
2
by: Steven O. | last post by:
First, this may not be the correct newsgroup. I have some relatively basic questions on SQL. I tried to find a newsgroup that was specifically just about SQL, and was surprised to find that all...
4
by: Ramesh | last post by:
hi, Let me ask some basic questions. Can anybody explain me about the following questions: 1. When we have to create sn key? Whenever we compiled Component we have to create or it is a one time...
3
by: Jim H | last post by:
If there is a site someone can point me to that answers such basic questions, rather than taking up support's time posting answers, please let me know. I've developed C# .NET, unmanaged C++, and...
2
by: Fay Yocum | last post by:
BEWARE beginner questions!! I have some experience in Access but never as much as I want or need. I have decided to get in on VB.Net. I would only rate myself in Access as a...
9
by: PCI | last post by:
A Thread is created on form1 that addresses a sub in another class. When attempting to invoke and sub on the main form I recieve an error about a Window Handler needing to be created first. Is...
0
by: software2006 | last post by:
ASP And Visual Basic Interview questions and answers I have listed over 100 ASP and Visual Basic interview questions and answers in my website...
4
by: Goran Djuranovic | last post by:
Hi all, I am experiencing a strange thing happening with a "designer.vb" page. Controls I manually declare in this page are automatically deleted after I drop another control on a ".aspx" page. -...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.