Shutdown a thread waiting on a timer in a Windows Service - c#

I have a .Net 4.0 C# Windows Service which spawns a number of thread which run continuously. Each thread runs at different intervals based on a timer.
I want to shut these threads down gracefully when the service is shutdown.
Since some of these threads may be waiting for hours to do it's processing, I need to wake them up and tell them to exit.
I could create a loop in these threads to periodically check some global variable at some interval less that their processing interval, but I would prefer a signaling mechanism which would cause them the timer to pop prematurely.
How can I wake these threads waiting on a timer without using Thread.Abort or Thread.Interrupt?

I'm going to assume that you have a good reason for using independently managed threads to do the work (as opposed to just doing it in the timer's event). If so, you want to use WaitHandle.WaitAny() and examine the return value to determine which WaitHandle caused the thread to proceed:
public class ExampleService
{
private static readonly AutoResetEvent TimerLatch = new AutoResetEvent(false);
private static readonly AutoResetEvent ShutdownLatch = new AutoResetEvent(false);
private static readonly Timer MyTimer = new Timer(TimerTick);
public void Start()
{
var t = new Thread(DoLoop);
t.Start();
MyTimer.Change(0, 500);
}
public void Stop()
{
ShutdownLatch.Set();
}
private static void TimerTick(object state)
{
TimerLatch.Set();
}
private static void DoLoop()
{
if (WaitHandle.WaitAny(new[] { TimerLatch, ShutdownLatch }) == 0)
{
// The timer ticked, do something timer related
}
else
{
// We are shutting down, do whatever cleanup you need
}
}
}

You can use WaitHandle.Waitone with a timeout and use events
if (shutDownEvent.WaitOne(_timeout, false ))
{
//Shutdown
}
else
{
//timeout so Dowork
}

Depending on your scenario it might be an option to make the threads you spawn background threads so you don't have to worry about explicitly shutting them down.
Thread thread = new Thread(DoSomething)
{
IsBackground = true
};
Setting IsBackground to true makes the spawned thread a background thread which won't stop your service from terminating.
From MSDN:
A thread is either a background thread or a foreground thread.
Background threads are identical to foreground threads, except that
background threads do not prevent a process from terminating. Once all
foreground threads belonging to a process have terminated, the common
language runtime ends the process. Any remaining background threads
are stopped and do not complete.
This of course is only an option if whatever operation you are performing may be interrupted and don't have to gracefully shut down (e.g. do some critical cleanup work). Otherwise as both other answers are suggesting you should use a WaitHandle, and signal from the main thread.

Related

Why the thread doesn't joins when closing application?

I made a WPF application with a progressbar. The value of the progressbar is getting updated to a random value in a "while"-loop in the function "Background_Work". This function runs in a seperate thread.
If I close the window, I want to end the function (by ending the "while"-loop) and join the thread.
The problem is, that in some cases the window freezes and doesn't close.
public partial class MainWindow : Window
{
Random random;
Thread background_work;
bool running;
public MainWindow()
{
InitializeComponent();
random = new Random();
background_work = new Thread(Background_Work);
running = true;
background_work.IsBackground = true;
background_work.Start();
}
private void Background_Work()
{
while (running)
{
myBar.Dispatcher.Invoke(() => { myBar.Value = random.Next(0, 100); });
Thread.Sleep(1000);
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
running = false;
background_work.Join();
}
}
I think what's happening is a combination of two things, which together cause a deadlock.
The first is that the running field is accessed from multiple threads, but isn't synchronized. If you access data from multiple threads, it must be locked. In this case, after the main thread sets the field to false, the background thread may read it as true for a while.
The second is that you call Dispatcher.Invoke, not Dispatcher.BeginInvoke. Invoke will post a message to the dispatcher's message queue, and will wait until that message has been processed, blocking the calling thread.
So what happens is:
The dispatcher thread sets running to false
The dispatcher thread blocks, waiting for the background thread to exit
The background thread finishes its sleep, incorrectly reads running as true, posts a message to the dispatcher thread's message queue, and blocks waiting for it to be processed
The message will never be processed, because the dispatcher thread is blocked waiting for the background thread to exit
The background thread will never exit, because it is blocked waiting for the message to be processed by the dispatcher thread
Deadlock
This is happening because you're breaking a number of different cardinal rules:
Never block the UI thread. Ever.
Never access shared state from two threads without a lock (or other synchronization). Ever.
Only use Invoke over BeginInvoke if you have a really good reason.
As the comments say, use a DispatcherTimer for this.
If you do find yourself needing to cancel a background thread, use a CancellationToken.
Calling background_work.Join() blocks the currently thread while it waits for the background_work thread to naturally finish. You have that tread busy in a while loop so it never ends and thus your UI is waiting forever.
I'd suggest you avoid threads all together and use Microsoft's Reactive Framework (NuGet System.Reactive.Windows.Threading for the WPF bits).
Then you can do this:
public partial class MainWindow : Window
{
Random random;
IDisposable subscription;
public MainWindow()
{
InitializeComponent();
random = new Random();
subscription =
Observable
.Interval(TimeSpan.FromSeconds(1.0))
.ObserveOnDispatcher()
.Subscribe(_ => myBar.Value = random.Next(0, 100));
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
subscription.Dispose();
}
}
It makes things very easy.

Waiting for and terminating a thread after a given time without blocking in .NET 3.5

I have a WinForms application on .NET 3.5. In this form, the user triggers an operation which is executed in another thread (a BackgroundWorker to be precise) so as to not block the UI thread. I'm in MVP, so all this is being done by a presenter which interacts with an interface to the view (implemented by the Windows Form). So far so good.
I would like to introduce functionality whereby a timeout period is introduced for the background operation to complete before cancelling it. Sounds simple enough. But the background operation calls a single function on a third-party component which may never return, so the cancellation capabilities of the BackgroundWorker are of no use to me here. Also, the BackgroundWorker.RunWorkerCompleted allowed me to get back on the UI thread, so I need to wait for the timeout or success and be able to get back to my calling thread (namely the UI thread).
I tried this using a plain old Thread (which does support Abort()) and a Timer running on a second thread, but can't seem to get it to work quite right since Join() is blocking my UI thread despite the description stating that it will block "while continuing to perform standard COM and SendMessage pumping". Admittedly I assumed this implied that it would continue to process Windows Messages, which was not the case.
int timeoutInMsec = 10000;
Thread connectThread = new Thread(Connect);
Thread timerThread = new Thread(() =>
{
var timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
timer.Tick += (_s, _e) =>
{
timer.Stop();
if (connectThread.ThreadState == ThreadState.Running)
connectThread.Abort();
};
};
connectThread.Start();
timerThread.Start();
timerThread.Join();
connectThread.Join();
Based on this question, I tried removing the second timer thread and adding a ManualResetEvent and calling Set() when the timer ticked, or when the Connect method did indeed complete. Here, instead of Join I used WaitOne, but unfortunately this also blocks my UI thread. I also found this other question, which a CancellationTokenSource which unfortunately is not available in .NET 3.5.
So, how can I spin my worker up and be able to terminate it after a given amount of time in .NET 3.5, while at the same time be able to get back to the thread where I spun up the worker thread to execute a sort of OnCompleted handler?
Many thanks in advance!
PS: I don't have a lot of experience in multi-threaded programming in .NET, so I'm sorry if this is trivial.
If I understood your question correctly, the following algorithm should solve your problem:
As before, create a BackgroundWorker to do your background work.
In BackgroundWorker_DoWork,
create a new thread (let's call it the "third-party thread") to call your third-party library, and then
wait for the third-party thread to finish or the timeout to elapse. (*)
That way, your UI won't block, since only the Backgroundworker thread is waiting, not the main thread.
Now about the interesting part: How do you wait for the third-party thread to finish (the step marked with (*))?
My suggestion would be to simply use "loop waiting with sleep", i.e. (pseudo-code, you can use the Stopwatch class for the timeout):
do until (third-party thread has finished or x seconds have elapsed):
Thread.Sleep for 100ms
if third-party thread has not finished:
Abort it // we don't have another choice
else
Process the result
It's not best practice, but it's simple, it gets the job done and you can always replace it with fancy cross-thread-syncronization stuff (which is non-trivial to get right) once you got it all working.
It's useless to create a Forms.Timer on a non-gui thread. Don't create it on a separate thread. Why are you Joining the threads? The usage of Join is to block the current thread until the other thread is finished.
This is untested pseudo code, this is for example purpose.
public class Form1: Form1
{
private int timeoutInMsec = 10000;
private System.Windows.Forms.Timer _timer;
private Thread _connectThread;
public Form1()
{
_connectThread = new Thread(Connect);
_connectThread.Start();
_timer = new System.Windows.Forms.Timer() { Interval = timeoutInMsec };
_timer.Tick += (_s, _e) =>
{
_timer.Stop();
if (_connectThread.ThreadState == ThreadState.Running)
_connectThread.Abort();
};
};
}
private void Connected()
{
}
private void Aborted()
{
}
private void Connect()
{
try
{
DoConnect3rdPartyStuff();
this.Invoke(Connected);
}
catch(ThreadAbortException)
{
// aborted
this.Invoke(Aborted);
}
}
}

When to use and what is the difference of a timer and thread?

Just now have some confusion about timer and thread, see below example, Both codes provide the same result (Do some checking every 60 seconds), so when should I use a timer and when should I use a thread to handle jobs when they're providing the same result?
Use Thread:
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
Thread.Sleep(60000);
}
Use Timer:
public Form1()
{
InitializeComponent();
Timer time = new Timer();
time.Interval = 60000;
time.Tick += time_Tick;
time.Enabled = true;
}
void time_Tick(object sender, EventArgs e)
{
//Do Checking here
}
If the task that is performed periodically is very short, and will not get in the way of processing on the thread that the timer runs, then a timer is a reasonable choice.
On the other hand, if the periodic task takes a significant amount of time, and you cannot afford to have the main thread interrupted to perform it, then a separate dedicated thread is a good choice.
It depends on the timer you're using. If you're using a WinForms timer then your callback will fire on the gui thread. If you've got a lot of work to do then this will cause your application to block until you've finished, which will make for a bad user experience.
If you're using one of the other timers then they'll fire on a thread in the thread pool. Even here you'll want to avoid doing anything to long, but it won't block your gui thread. However, you're need to ensure you marshal any calls into the gui using the BeginInvoke method.
Starting your own thread is good if you're got long running tasks to do every time the timer fires, but once again you'll want to marshal calls back to the gui thread. Rather than using Thread.Sleep it's better to use an Event so that you can detect when the rest of the system is shutting down:
ManualResetEvent stopEvent = new ManualResetEvent(false);
Thread checkJob = new Thread(checkStatus);
checkJob.Start();
protected void checkStatus()
{
//Do Checking here
while(stopEvent.Wait(60000) == false)
{
// Do processing
}
}
Now you can stop the thread by calling stopEvent.Set()
You can view a thread as a "sub-process"; a process can have multiple threads, allowing it to perform several operations in parallel. A thread is an expensive system resource; it uses a CPU when it's active, and allocates its own call stack (1MB by default). Using a thread to perform periodic actions is a waste of precious resources, and doesn't scale well.
A timer, in the other hand, is much cheaper. It's just a time-controlled trigger that does nothing most of the time, except when it's time to execute your code. It's the right choice in your case.
I would recommend to use Timer - it is more suitable when it comes to resource consumption.
Setting up a new thread is quite expansive.
By the way in case you would like to use Thread you should set it to IsBackground=true, so that it can finish its execution when the application is shutdown.

Expected ThreadAbort for Background Thread

I have the following.
public static Thread testThread = new Thread(ThreadStart) {Name = "TestThread", IsBackground = true};
private void Form_Load()
{
testThread.Start()
}
private static void ThreadStart()
{
int count = 0;
try
{
while (true)
{
count++;
}
}
catch (Exception ex)
{
StreamWriter stream = new StreamWriter(File.OpenWrite("Exception.txt"));
stream.WriteLine(count + "\n" + ex);
stream.Flush();
stream.Close();
}
}
When I call Thread.Abort() I catch the exception and write out to the file.
However, if I instead close the application nothing is written.
I also have
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
But it doesn't appear an exception is ever thrown.
I suppose adding a question is prudent.
What happens to a running background thread when the parent processes exits?
My understanding was a ThreadAbortException is thrown to exit the thread.
If this is the case, how can the ThreadAbortException be caught in order to clean up resources that may be present in the thread?
First of all, the application probably isn't exiting, because you are not making these into background threads. My guess is that Task Manager will show copies of your EXE running unexpectedly. You need to set Thread.IsBackground to true on the thread object before calling Start.
Secondly, the behavior that you expect is explicitly debunked by the documentation:
Note
When the common language runtime (CLR) stops background threads,
after all foreground threads in a managed executable have ended, it
does not use System.Threading.Thread.Abort. Therefore, you cannot use
ThreadAbortException to detect when background threads are being
terminated by the CLR.
EDIT:
When a process is exiting, there is no need to clean up resources held by the worker threads because, you know, the process is exiting. The contract with regard to background threads is that they can be killed at any time when the process exits. Therefore, if your background threads are doing something that requires transactional correctness, they probably should not be background threads. Make 'em foreground threads and have them periodically check or wait on a reset event to see whether they should exit and allow the process to end.
When the CLR shuts down a process it does not call Thread.Abort or anything similar. Your thread methods will not exit like your main method.
The first thing it does when you leave the main method or call Environment.Exit is to finalize all objects with a timeout (it was 2s in .NET 2.0) then it will continue to terminate the application regardless of the current pending finalizers.
Next the Critical Finalizers are called.
Then all threads are suspended so they do not cause harm while the CLR is shutting down.
You application has exited.
If the IsBackground property of your thread is false, then your thread would remain alive, even when the main window of your application is closed.
The best way to control the lifetime of background threads is to create sentinels, typically implemented as volatile bool fields, which the code within the thread checks at regular intervals (for example, on every iteration). The thread should stop executing when the sentinel indicates that the application is terminating.
The following code shows the use of a sentinel to terminate the thread after 200 milliseconds:
public static Thread testThread = new Thread(ThreadStart)
{
Name = "TestThread",
IsBackground = false // Allow thread to terminate naturally
};
private static volatile bool isTerminating = false; // Sentinel
private void Form_Load()
{
testThread.Start();
Thread.Sleep(200); // Sleep 200 milliseconds
isTerminating = true; // Set sentinel to terminate thread
}
private static void ThreadStart()
{
int count = 0;
while (!isTerminating) // Keep looping until sentinel is set
count++;
using (StreamWriter stream = new StreamWriter(File.OpenWrite("Result.txt")))
{
stream.WriteLine(count);
stream.Flush();
}
}
Edit: To answer your last question, “How can the ThreadAbortException be caught in order to clean up resources that may be present in the thread?” You can use an ordinary catch block. ThreadAbortException may be caught like any other exception, but it will automatically be raised again at the end of the catch block. However, as Chris mentioned, if the process is exiting, the ThreadAbortException is not raised at all.

Shutting down a multithreaded application

I'm trying to write a ThreadManager for my C# application. I create several threads:
One thread for my text writer.
One thread that monitors some statistics.
Multiple threads to perform a large sequence of calculations (up to 4 threads per core and I run my app on a 2x quad core server).
My application normally runs for up to 24 hours at a time, so all the threads get created in the beginning and they persist through the entire time the app runs.
I want to have a single place where I "register" all of my treads and when the application is shutting down I simply invoke a method and it goes through all of the registered threads and shuts them down.
For that purpose I have devised the following class:
public class ThreadManager
{
private static Object _sync = new Object();
private static ThreadManager _instance = null;
private static List<Thread> _threads;
private ThreadManager()
{
_threads = new List<Thread>();
}
public static ThreadManager Instance
{
get
{
lock (_sync)
{
if (_instance == null)
{
_instance = new ThreadManager();
}
}
return _instance;
}
}
public void AddThread(Thread t)
{
lock (_sync)
{
_threads.Add(t);
}
}
public void Shutdown()
{
lock (_sync)
{
foreach (Thread t in _threads)
{
t.Abort(); // does this also abort threads that are currently blocking?
}
}
}
}
I want to ensure that all of my threads are killed so the application can close properly and shutting down in the middle of some computation is just fine too. Should I be aware of anything here? Is this approach good given my situation?
If you set the threads to background threads, they will be killed when the application is shut down.
myThread.IsBackground = true;
obviously if you need the threads to finish before shutdown, this is not the solution you want.
Aborting threads is what you do when all else fails. It is a dangerous thing to do which you should only do as a last resort. The correct way to do this is to make your threading logic so that every worker thread responds quickly and correctly when the main thread gives it the command to shut itself down.
Coincidentally, this is the subject of my blog this week.
http://blogs.msdn.com/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx
What if AddThread is called while your Shutdown is running?
When shutdown finishes, the thread waiting in AddThread will add a new thread to the collection. This could lead to hangs in your app.
Add a bool flag that you ever only set in Shutdown to protect against this.
bool shouldGoAway = false;
public void AddThread(Thread t)
{
lock (_sync)
{
if( ! shouldGoAway )
_threads.Add(t);
}
}
public void Shutdown()
{
lock (_sync)
{
shouldGoAway = true;
foreach (Thread t in _threads)
{
t.Abort(); // does this also abort threads that are currently blocking?
}
}
Also you should not use static members - there is no reason for that as you have your Singleton instance.
.Abort() does not abort threads that are blocking in unmanaged space. So if you do that you need to use some other mechanism.
The only specific issue I know about is this one: http://www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
But I'd avoid having to resort to a design like this. You could force each of your threads to check some flag regularly that it's time to shut down, and when shutting down, set that flag and wait for all threads to finish (with Join()). It feels a bit more like controlled shutdown that way.
If you don't care about the worker thread state then you can loop through _thread and abort:
void DieDieDie()
{
foreach (Thread thread in _thread)
{
thread.Abort();
thread.Join(); // if you need to wait for the thread to die
}
}
In your case you can probably just abort them all and shutdown as they're just doing calculations. But if you need to wait for a database write operation or need to close an unmanaged resource then you either need to catch the ThreadAbortException or signal the threads to kill themselves gracefully.
You want deferred thread cancellation, which basically means that the threads terminate themselves as opposed to a thread manager cancelling threads asynchronously, which is much more ill-defined and dangerous.
I you wanted to handle thread cancellation more elegantly than immediate termination, you can use signal handlers that are triggered by events outside the thread - by your thread manager perhaps.

Categories

Resources