Usually you're adviced to use something like that (using timeouts):
Thread workerThread = null;
AutoResetEvent finishedEvent = new AutoResetEvent(false);
protected override void OnStart(string[] args) {
this.finishedEvent.Reset();
this.workerThread = new Thread(this.Poll);
this.workerThread.Start();
}
protected override void OnStop() {
this.finishedEvent.Set();
if(!this.workerThread.Join(2000)) {
this.RequestAdditionalTime(5000);
}
}
where Poll function is defined like:
private void Poll() {
try {
var timeout = Int32.Parse(ConfigurationManager.AppSettings["pollingTimeout"]);
while(!this.finishedEvent.WaitOne(timeout, false)) {
// do polling
}
}
catch(Exception ex) {
Logger.Log.Fatal(ex);
throw;
}
}
Are these constructs essentially equal:
while(!this.finishedEvent.WaitOne(0, false))
and
while(true) with no finishedEvent?
I've read that timeouts are used to reduce the cpu usage. Is it a bad choice to use polling without timeouts?
There is a very simple way to do this providing you don't strictly need an orderly shutdown. If you mark the workerThread as a background thread, it will shut down automatically when the service stops. In this example, you can forego the use of the finishedEvent and use an infinite loop. For example,
Thread workerThread = null;
protected override void OnStart(string[] args)
{
this.workerThread = new Thread(this.DoWork);
// Signal the thread to stop automatically when the process exits.
this.workerThread.IsBackground = true;
this.workerThread.Start();
}
protected override void OnStop()
{
}
private void DoWork()
{
try
{
while (true)
{
// do your work here...
}
}
catch (Exception ex)
{
// handle exception here...
}
}
Note that this approach should only be used if the work you are doing can be interrupted at any point without adverse effects. Let's say for an example that you were writing data to an Excel spreadsheet. Once the the Windows service exits, the thread represented by your DoWork() method will also exit immediately. If it is in the middle of adding data to the spreadsheet, it is very likely that the spreadsheet could have incomplete information or, worse case, might even be in a state that it cannot be opened in Excel. The point is, this approach could be used, but only in certain circumstances.
A better approach would be to fully transition to an event-based mechanism. It is much more efficient than polling, and it allows for an orderly shutdown to your service. Below is an example with comments.
Thread _workThread = null;
// I use ManualResetEvent instead of AutoResetEvent because I do NOT want
// this event to EVER reset. It is meant to be set exactly one time.
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
_workThread = new Thread(DoWork());
_workThread.Start();
}
protected override void OnStop()
{
// Trigger the DoWork() method, i.e., the _workThread, to exit.
_shutdownEvent.Set();
// I always shutdown my service by simply joining the work thread.
// There are probably more advanced techniques that take into account
// longer shutdown cycles, but I design my worker thread(s) to have
// tight work cycles so that the shutdownEvent is examined frequently
// enough to facilitate timely shutdowns.
_workThread.Join();
}
Now let's look at the details of the DoWork() method. For this example, I'm gonna use a timer to illustrate the event-based approach. Note that this illustration is not substantively different from calling the WaitOne() method with a timeout. However, if the work to be done involves processing input from other threads, e.g., a thread that receives data from a network socket or a thread that reads data from a database, this approach easily accommodates those scenarios.
// Creature of habit. AutoResetEvent would probably work for this event,
// but I prefer to manually control when the event resets.
ManualResetEvent _timerElapsedEvent = new ManualResetEvent(false);
System.Timers.Timer _timer = null;
private void DoWork() {
try {
// Create, configure, and start the timer to elapse every second and
// require a manual restart (again, I prefer the manual control).
// Note when the timer elapses, it sets the _timerElapsedEvent.
_timer = new Timer(1000) { AutoReset = false };
_timer.Elapsed =+ (sender, e) => _timerElapsedEvent.Set();
_timer.Start();
// Create a WaitHandle array that contains the _shutdownEvent and
// the _timerElapsedEvent...in that order!
WaitHandle[] handles = new WaitHandle[] { _shutdownEvent, _timerElapsedEvent };
// Employ the event-based mechanism.
while (!_shutdownEvent.WaitOne(0)) {
switch (WaitHandle.WaitAny(handles) {
case 0:
// This case handles when the _shutdownEvent occurs,
// which will cause the while loop to exit.
break;
case 1:
// This case handles when the _timerElapsedEvent occurs.
// Do the work, reset the event, and restart the timer.
DoProcessing();
_timerElapsedEvent.Reset();
_timer.Start();
break;
}
}
} catch (Exception ex) {
// handle exception here...
}
}
The WaitHandle array is what makes the event-based mechanism possible. When you create the array, always be sure to add the events to the array in priority order. This is why the _shutdownEvent is listed before the _timerElapsedEvent. If the events were reversed in the array, it is possible that the _shutdownEvent would never get processed. You can add as many events to the WaitHandle array as necessary. That's what makes this approach so flexible.
Last thought. To facilitate timely shutdowns of your service, you want to make sure that work to be done when the _timerElapsedEvent is triggered doesn't take too long. In other words, the _shutdownEvent will not be checked by the while loop until the DoProcessing() method exits. So you'll want to limit the amount of time you spend inside the DoProcessing() method. If that method is long-running, then you'll probably want to check the _shutdownEvent inside DoProcessing() and exit at strategic points when the service has indicated it is shutting down.
Hope this helps.
Related
I have a worker thread that may be active for short bursts of time and idle for rest of the time. I'm thinking to put the thread to sleep and then awake it when needed.
Any additional recommendations for this I should be aware of?
Thanks!
this is in C#/.NET4
You should probably not be using a persistent worker thread- use the thread pool. This is exactly what it is intended for.
ThreadPool.QueueUserWorkItem(() => {
// My temporary work here
});
If you insist on having a persistent worker thread, make it run this:
// This is our latch- we can use this to "let the thread out of the gate"
AutoResetEvent threadLatch = new AutoResetEvent(false);
// The thread runs this
public void DoBackgroundWork() {
// Making sure that the thread is a background thread
// ensures that the endless loop below doesn't prevent
// the program from exiting
Thread.IsBackground = true;
while (true) {
// The worker thread will get here and then block
// until someone Set()s the latch:
threadLatch.WaitOne();
// Do your work here
}
}
// To signal the thread to start:
threadLatch.Set();
Also note that if this background thread is going to interact with the user interface at all, you'll need to Invoke or BeginInvoke accordingly. See http://weblogs.asp.net/justin_rogers/pages/126345.aspx
Just use an event to pause the worker thread: reset - paused, set - unpaused (working) state.
Here is the draft version of code that demonstrates the approach.
class Worker
{
private Thread _thread;
// Un-paused by default.
private ManualResetEvent _notToBePaused = new ManualResetEvent(true);
public Worker()
{
_thread = new Thread(Run)
{
IsBackground = true
};
}
/// <summary>
/// Thread function.
/// </summary>
private void Run()
{
while (true)
{
// Would block if paused!
_notToBePaused.WaitOne();
// Process some stuff here.
}
}
public void Start()
{
_thread.Start();
}
public void Pause()
{
_notToBePaused.Reset();
}
public void UnPause()
{
_notToBePaused.Set();
}
}
Signaling with WaitHandle is the right way to go, but just to add on what others said already
I'd usually go with 2 signals working together, otherwise you wouldn't know whether to 'continue' or 'exit' when needed - or would have to resort to a less graceful way of doing that (stopping the thread - of course there are other ways of doing something like this, just one 'pattern'). So usually it works with an 'exit' signal and a 'new work available' signal - working in unison. e.g.
WaitHandle[] eventArray = new WaitHandle[2] { _exitEvent, _newWorkEvent };
while ((waitid = WaitHandle.WaitAny(eventArray, timeout, false)) > 1)
{
// do your work, and optionally handle timeout etc.
}
note:
exit is ManualResetEvent with 'false' initial state - 'Set' event to exit.
_newWork is either Manual in which case you need to pause/continue from outside which is what you wanted I think -
...or could also be new AutoResetEvent(false) which you 'signal' to do one loop of work, signal returns to 'false' right away - and you need to repeat that for each 'new batch' of work - this is a bit simplified.
(often that goes hand in hand with some 'messages' being passed along, synchronized of course in some way).
Hope this adds some more info,
Working on a windows service, which has to process request in every predefined interval of time. Thread.Sleep does the work perfectly fine but problem with this is when service is invoked to be stopped, service freeze if thread is in sleep mode.
I have read about the alternative approach like Timer, but problem with that is after that defined interval new thread is getting started.
Is there a better way to achieve same result and not run in to issue.
What you're looking for is the ability to respond to the notification of two different events - (1) when the timer elapses and (2) when the service is stopped. #Anurag Ranhjan is on the right track with WaitHandle, but you have two events, not one. To properly handle this, do the following.
First, define the two events you care about using ManualResetEvent. You can use AutoResetEvent if you prefer; I just prefer resetting the events manually.
using System.Threading;
ManualResetEvent shutdownEvent = new ManualResetEvent();
ManualResetEvent elapsedEvent = new ManualResetEvent();
You need to trigger these events when they occur. For the shutdownEvent, it's easy. In the OnStop callback of your Windows service, just set the event.
protected override void OnStop
{
shutdownEvent.Set();
}
For the elapsedEvent, you could do this a couple different ways. You could create a background thread, i.e., the ThreadPool, that uses Thread.Sleep. When the thread wakes up, set the elapsedEvent and go back to sleep. Since it's a background thread, it won't hang your service when it shuts down. The alternative, as you've already suggested, is to use a timer. This is how I do it.
using System.Timers;
Timer timer = new Timer();
timer.Interval = 5000; // in milliseconds
timer.Elapsed += delegate { elapsedEvent.Set(); };
timer.AutoReset = false; // again, I prefer manual control
timer.Start();
Now that you've got events being set properly, put them in a WaitHandle array.
WaitHandle[] handles = new WaitHandle[]
{
shutdownEvent,
elapsedEvent
};
Instead of the WaitHandle.WaitOne method, use the WaitHandle.WaitAny method inside a while loop, like this.
while (!shutdownEvent.WaitOne())
{
switch (WaitHandle.WaitAny(handles))
{
case 0: // The shutdownEvent was triggered!
break;
case 1: // The elapsedEvent was triggered!
Process(); // do your processing here
elapsedEvent.Reset(); // reset the event manually
timer.Start(); // restart the timer manually
break;
default:
throw new Exception("unexpected switch case");
}
}
I've condensed this example from production code in my project. I know this mechanism works, but I may have missed something in the writeup. Let me know if you have any questions.
You can use WaitHandle.WaitOne instead. You can wait for closing event to trigger or timeout that you are specifying in predefined interval of time.
static AutoResetEvent seviceStopRequested = new AutoResetEvent(false);
....
((AutoResetEvent)stateInfo).WaitOne([timeout], false)
Then when Service stop is invoked, you can just trigger the event
seviceStopRequested .Set();
I usually use the following pattern:
public class MyJob
{
System.Threading.Timer _timer;
bool _isStopped;
public void MyJob()
{
_timer = new Timer(OnWork, null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
private void OnWork(object state)
{
//[.. do the actual work here ..]
if (!_isStopped)
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
public void Stop()
{
_isStopped = true;
_timer.Change(TimeSpan.FromSeconds(-1), TimeSpan.FromSeconds(-1));
}
public void Start()
{
_isStopped = false;
_timer.Change(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(-1));
}
}
Key points:
Only using the initial interval gives you full control of when the timer is started again (i.e. the work time is not counted in the timer interval)
Changing the timer to -1 seconds pauses it until changed again
It should therefore work with all your requirements.
Use a Timer to add commands/tasks including the task for shutdown to a blocking queue. Make your service thread to wait for tasks on the blocking queue and execute them when available. The timer thread will keep adding the tasks to the queue periodically.
For what it is worth most of the blocking calls in the .NET BCL will respond to Thread.Interrupt. That is, they will not wait for the full amount of time specified when called and instead return immediately. However, I would avoid using this method and instead use a single ManualResetEvent to perform both the idle waiting and the shutdown signal. It would look like this.
public class MyServer : ServiceBase
{
private ManualResetEvent shutdown = new ManualResetEvent(false);
protected override void OnStart(string[] args)
{
new Thread(
() =>
{
while (!shutdown.WaitOne(YourInterval))
{
// Do work here.
}
}).Start();
}
protected override void OnStop()
{
shutdown.Set();
}
}
Summary:
Within a Windows service & Console Application I am calling a common library that contains a Timer that periodically triggers an action that takes around 30 seconds to complete. This works fine, however...
When a service stop or application exit is called and the timer is in the ElapsedEventHandler I need the service stop/application exit to wait until the event handler has completed.
I have implemented this functionality by having a Boolean InEvent property that is checked when the timer stop method is called.
While this is functional, the question is: Is this the best way to go about doing this? Is there an alternative approach that may serve this purpose better?
The other issue is that I need to avoid the service stop request failing with a "Service failed to respond to stop request"
This is my implementation
public sealed class TimedProcess : IDisposable
{
static TimedProcess singletonInstance;
bool InEvent;
Timer processTimer;
private TimedProcess()
{
}
public static TimedProcess Instance
{
get
{
if (singletonInstance == null)
{
singletonInstance = new TimedProcess();
}
return singletonInstance;
}
}
public void Start(double interval)
{
this.processTimer = new Timer();
this.processTimer.AutoReset = false;
this.processTimer.Interval = interval;
this.processTimer.Elapsed += new ElapsedEventHandler(this.processTimer_Elapsed);
this.processTimer.Enabled = true;
}
public void Stop()
{
if (processTimer != null)
{
while (InEvent)
{
}
processTimer.Stop();
}
}
void processTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
InEvent = true;
// Do something here that takes ~30 seconds
}
catch
{
}
finally
{
InEvent = false;
processTimer.Enabled = true;
}
}
public void Dispose()
{
if (processTimer != null)
{
Stop();
processTimer.Dispose();
}
}
}
And this is how it is called in the service OnStart / console application main:
TimedProcess.Instance.Start(1000);
This is how it is called in service OnStop and application main (pending keypress):
TimedProcess.Instance.Stop();
Probably the easiest and most reliable way is to use a Monitor. Create an object that the main program and the timer callback can access:
private object _timerLock = new object();
Your main program tries to lock that before shutting down:
// wait for timer process to stop
Monitor.Enter(_timerLock);
// do shutdown tasks here
And your timer callback locks it, too:
void processTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!Monitor.TryEnter(_timerLock))
{
// something has the lock. Probably shutting down.
return;
}
try
{
// Do something here that takes ~30 seconds
}
finally
{
Monitor.Exit(_timerLock);
}
}
The main program should never release the lock once it's obtained it.
If you want the main program to go ahead and shut down after some period of time, regardless of whether it's obtained the lock, use Monitor.TryEnter. For example, this will wait 15 seconds.
bool gotLock = Monitor.TryEnter(_timerLock, TimeSpan.FromSeconds(15));
The return value is true if it was able to obtain the lock.
By the way, I strongly suggest that you use System.Threading.Timer rather than System.Timers.Timer. The latter squashes exceptions, which can end up hiding bugs. If an exception occurs in your Elapsed event, it will never escape, meaning that you never know about it. See my blog post for more information.
EDIT
Each callback to the System.Timers.Timer is queued on the ThreadPool. Be aware that the System.Timers.Timer can have a race condition (you can read more about it here.) System.Threading.Timer is a slightly nicer wrapper which I prefer to use due to it's simplicity.
You haven't described enough details to know if your particular application could handle that race condition, so it's hard to tell. But given your code, it is possible that there might be a callback queued up for processTimer_Elapsed after Stop() is called.
For the service timeout issue --
One way to do this is to make a call to the ServiceController method WaitForStatus with a timeout. I've done this in the past and it works reasonably well, although I recall there being some edge cases around waiting for a very long time.
See the MSDN reference. A sample use is described here.
One possible alternative seems to be to not do the actual work in the timer callback itself but to just queue a work item from there on the tread pool to do the work. Then you can go ahead and dispose of the timer - anything currently running on the thread pool will remain operational, and your service can respond to the stop request immediately but the thread pool item (if queued) will still get processed.
I've been working on a thread which will live as long as the application is running, and runs at a interval of 500ms. I noted that I could be uselessly processing if there's nothing in the queue for it to process, so I went around looking at some sources I had locally, and I found an example close to mine, but it's in Java.
The example had this:
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
cleanup();
break;
}
}
Inside a while loop which goes on forever.
The thread has this to notify the wait:
synchronized(this) {
notifyAll();
}
This was inside the enqueue thread.
I'd also like you to note that the class inherits Runnable.
Could anyone quickly explain the corresponding functions in C#? And maybe an example if you could!
.NET/C# best practice would be to use an EventWaitHandle.
You'd have some variable shared between the threads as so:
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
In the consumer thread (the one that you're waking up every 500ms right now), you'd loop waiting for the handle (perhaps with a timeout):
try
{
while(true)
{
handle.WaitOne();
doSomething();
}
}
catch(ThreadAbortException)
{
cleanup();
}
And in the producer thread:
produceSomething();
handle.Set();
Maybe you can use a blocking queue : http://www.eggheadcafe.com/articles/20060414.asp
It's a Queue except Dequeue function blocks until there is an object to return.
Usage:
BlockingQueue q = new BlockingQueue();
void ProducerThread()
{
while (!done)
{
MyData d = GetData();
q.Enqueue(d);
Thread.Sleep(100);
}
}
void ConsumerThread()
{
while (!done)
{
MyData d = (MyData)q.Dequeue();
process(d);
}
}
The consumer thread only executes when there is something in the queue to process, and doesn’t waste CPU time polling when there is nothing to do.
Use a timer that fires every 500ms and let your timer handler do the work. Timer handler threads run in the thread pool. Read about it here: http://www.albahari.com/threading/part3.aspx#_Timers.
System.Timers.Timer timer = new System.Timer(500);
timer.Elapsed += new System.Timers.ElapsedEventHandler (MyTimerHandler);
timer.Start();
private void TimerHandler(object sender, System.Timers.ElapsedEventArgs e)
{
// optional - stop the timer to prevent overlapping events
timer.Stop();
// this is where you do your thing
timer.Start();
}
You might want to download and read Joe Albahari's free ebook on threading in C#. It's a great introduction and reference.
Threading in C#
Not exactly sure on the terminology here but here I go basically I have the main() thread of my application that starts and calls two threads, one sets up an event handler to wait for specific registry keys to change, while the other starts a timer to write any changes made to an xml file every 5 mins or so and runs continuously. The issue I have is that once the two methods called are initialized it goes back to main and ends the program. My relevant code sections can be found below, so any help would be appreciated:
static void Main(string[] args)
{
runner one = new runner();
runner two = new runner();
Thread thread1 = new Thread(new ThreadStart(one.TimerMeth));
Thread thread2 = new Thread(new ThreadStart(two.start));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
}
public void TimerMeth()
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 300000;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
file write = new file();
write.write(RegKeys);
}
public void start()
{
if (File.Exists("C:\\test.xml"))
{
file load = new file();
RegKeys = load.read(RegKeys);
}
string hiveid = "HKEY_USERS";
WindowsIdentity identity = WindowsIdentity.GetCurrent();
string id = identity.User.ToString();
string key1 = id + "\\\\Software\\\\Microsoft\\\\Windows NT\\\\CurrentVersion\\\\Windows Messaging Subsystem\\\\Profiles\\\\Outlook\\\\0a0d020000000000c000000000000046";
List<string> value1 = new List<String> { "01020402", "test" };
valuechange = new RegistryValueChange(hiveid, key1, value1);
valuechange.RegistryValueChanged += new EventHandler<RegistryValueChangedEventArgs>(valuechange_RegistryValueChanged);
try
{
valuechange.Start();
}
catch
{
StreamWriter ut;
ut = File.AppendText("C:\\test.txt");
ut.WriteLine("error occured in starting management");
ut.Close();
}
file test = new file();
test.checkfile("C:\\test.xml");
}
void valuechange_RegistryValueChanged(object sender, RegistryValueChangedEventArgs e)
{
// deals with the returned values
}
Basically all the code works fine I've been testing it in a windows form application but now I need to run it in a standalone app with no interface in the background and need it to keep writing to the xml file and the change event to stay alive.
As you can expect, the Main() method is terminating because execution flows out of the Join() methods back to the main thread, and then terminates.
Either place loops in the methods TimerMeth() and start(), or more appropriately redesign the application into a Windows Service (as zac says).
You have a couple of issues.
Your first thread is simply creating a timer (which launches another thread). This thread is terminating very quickly, making your call to Join rather meaningless. What this thread should be doing is actually doing the waiting and the checking. You can easily adapt your code like this:
public void TimerMeth()
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 300000;
timer.Enabled = true;
try
{
while(true)
{
OnElapsedTime(null, null); // you should change the signature
Thread.Sleep(30000);
}
}
catch(ThreadAbortException)
{
OnElapsedTime(null, null);
throw;
}
}
Obviously you should change the signature of OnElapsedTime to eliminate the parameters, since they aren't used here.
I have a feeling that something is amiss in the way that the file handling is being done, but given that I don't understand exactly what that code does, I'm going to refrain from commenting. What, exactly, is the purpose of the file? Where is RegKeys defined?
Try building this into a windows service.
This thread contains two suggestions for finding the logged on user from a windows service, but I am not sure if they work.
Your methods will run once, then the thread will exit. There is nothing to keep them running.
Try this:
thread1.IsBackground = true;
thread2.IsBackground = true;
public void start()
{
while(true)
{
// ... do stuff
Thread.Sleep(1000*60*5) // sleep for 5 minutes
}
}
public void TimerMeth()
{
while(true)
{
file write = new file();
write.write(RegKeys);
Thread.Sleep(30000);
}
}
As other posters have noted, you will also then need to ensure your main method doesn't exit. Making the application a windows service seems like a good way to solve this in your case.
You might also want to handle ThreadInterruptedException and ThreadAbortException on your threads.
And if you really want to get into the nitty gritty of threading, check out this Free C# Threading E-Book by Joe Albahari.
To keep the main thread alive, one of the simplest ways is to add the following line to the end of your main function:
Thread.Sleep(Timeout.Infinite);
The Thread will terminate when your ThreadStart function returns, which allows the main thread to continue after Join(). Since you are just setting up a timer to fire off, the method will return very quickly. You need to provide a lock of some sort to keep your application from exiting.
Also, it doesn't look like you need to use threads at all to do what you are trying. Instead, just use the Timer and provide the lock to keep your Main() from terminating.
It looks to me like all of your functions are completing? ie, they all "fall out the bottom". Once all the functions have run through there is nothing left to do and your app will close. You want to run a loop of some sort in main.
You will also need to take a look at your timer. I suspect it is currently being garbage collected. You create it in the scope of your function but that function is being left so there is no longer a reference to your timer and it will be collected. Your timer needs to be a root.