Alternative to Thread.Sleep - c#

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();
}
}

Related

The common practice for polling inside Windows services

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.

C# Pause Program Execution

I am writing a program that will perform an operation every 10 or 15 minutes. I want it to be running all the time, so I need something that is cheap on processing power. What I have read so far seems to suggest that I want to use a Timer. Here is a clip of the code I have so far.
class Program {
private static Timer timer = new Timer();
static void Main(string[] args) {
timer.Elapsed += new ElapsedEventHandler(DoSomething);
while(true) {
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
}
}
}
The problem here is that the while loop just keeps executing rapidly. How do I halt execution until the timer is elapsed. My program really doesn't need to be multi threaded. Is a Timer the right tool for this job?
Thank you in advance for any help!
UPDATE: Sorry for the confusion. I have implemented the DoSomething method. I just did not include it as I don't believe it is part of my issue.
Timer's will fire off the Elapsed event once the specified interval has elapsed.
I would do something like this:
private static Timer timer = new Timer();
static void Main(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(DoSomething);
timer.Interval = TimerMilliseconds(); // The duration of the wait will differ each time
timer.Enabled=true;
Console.ReadKey(); //Wait for keypress to terminate
}
You could also implement this as a service so you don't have to have a blocking call like Console.ReadKey to keep the program from terminating.
Finally, you could just change the interval in the event handler:
static void DoSomething(...)
{
timer.Stop();
timer.Interval = TimerMilliseconds();
...
timer.Start();
}
The problem with this code is that you're using a loop to set the Interval and Enabled properties of the Timer, which will execute said assignments over and over - it's not waiting for the timer to execute in some way.
If your application doesn't need to be mutlithreaded, then you might be better simply calling Thread.Sleep between executions.
class Program {
static void Main(string[] args) {
while(true) {
Thread.sleep(TimerMilliseconds()); // The duration of the wait will differ each time
DoSomething();
}
}
}
take out the timer and loop from your logic. Just use windows scheduler to execute your program after 15 minutes. Or you can use windows services. Please read Best Timer for using in a Windows service
remove the while loop completely.
inside of the DoSomething() function (once implemented) stop timer at start and at the end reset the interval before restarting the timer.
I guess the comments and answrs already provide the hints you need, but the MSDN docs for Timer actually provide a nice example. In my opinion the Timer approach is a bit tidier, it's easier to read your intentions and abstracts away the details of invoking your scheduled code.
Here's another alternative approach using ManualResetEvent and WaitOne(). This will allow you to halt the main thread without worrying about it being killed accidentally by an errant keypress. You can also Set() the MRE when certain conditions are met to allow the app to exit gracefully:
class Program
{
private static Timer timer;
private static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
timer = new Timer(TimerCallback, null, 0, (int)TimeSpan.FromMinutes(15).TotalMilliseconds);
mre.WaitOne();
}
private static void TimerCallback(object state)
{
// ... do something in here ...
Console.WriteLine("Something done at " + DateTime.Now.ToString());
}
}

Waiting for a timer elapsed event to complete before application/service closes/stops

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.

Windows Forms Timer doesn't stop. How is that possible?

During debugging I can see that after Timer.Stop() or Timer.Enabled = false commands are executed, Timer is still running (Timer.Enabled = true). How is that possible?
This is possible when you stop the timer on a worker thread. For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
Timer timer1;
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
timer1 = new Timer();
timer1.Interval = 3000;
timer1.Start();
var t = new System.Threading.Thread(stopTimer);
t.Start();
}
private void stopTimer() {
timer1.Enabled = false;
System.Diagnostics.Debug.WriteLine(timer1.Enabled.ToString());
}
}
Output:
True
The timer must be stopped by the UI thread, the class takes care of it automatically. Quite similar to Control.BeginInvoke(). There's an explicit race, the Tick event handler can run after you stopped it. This can also happen on the UI thread if the very first timer you create is created on a worker thread. A splash screen for example. That's not healthy, you ought to fix that.
Calling Start after you have disabled a Timer by calling Stop will cause the Timer to restart the interrupted interval. If your Timer is set for a 5000-millisecond interval, and you call Stop at around 3000 milliseconds, calling Start will cause the Timer to wait 5000 milliseconds before raising the Tick event.
bear also in mind
Calling Stop on any Timer within a Windows Forms application can cause messages from other Timer components in the application to be processed immediately, because all Timer components operate on the main application thread. If you have two Timer components, one set to 700 milliseconds and one set to 500 milliseconds, and you call Stop on the first Timer, your application may receive an event callback for the second component first. If this proves problematic, consider using the Timer class in the System.Threading namespace instead.
http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.stop.aspx
public void EnableTimer(bool state)
{
if (this.InvokeRequired) {
this.Invoke(new Action<bool>(EnableTimer), state);
} else {
this.Timer1.Enabled = state;
}
}
Try this code...

Quick C# threading class

Got a quick question on creating a C# thread.
It needs to run every 10 minutes
The worker will do work then go into sleep for another 10 minutes
It can also be triggered to run immediately by calling Trigger()
It can be stopped by calling Stop()
I've created one with ManualResetEvent, which is set when Stop() is called. This works well but do I need to create another ManualResetEvent or wait handle in order to be able to trigger the worker immediately?
If by Stop you mean Stop waiting and don't run again then I think a Threading.Timer will be a good (lean) choice.
You can activate a timer with a DoWork() method and a 10 minutes interval. It will use the ThreadPool which seems the best choice here. Trigger() can queue DoWork directly on the Pool and Stop() can deactivate the Timer. DoWork() shouldn't use Sleep() and be suitable for the ThreadPool.
Using a timer here makes sense. Here's a quick code-snippet which I haven't tested.
private System.Timers.Timer _timer = null;
public void Constructor()
{
_timer = new System.Timers.Timer(600000);
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void ForceDoWork()
{
//unsubscribe to timer event, so work dowsnt get fired twice
_timer.Elapsed -= new ElapsedEventHandler(t_Elapsed);
StartWorking();
_timer.Elapsed += new ElapsedEventHandler(t_Elapsed);
}
public void StartWorking()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkToBeDone));
}
private void WorkToBeDone(object state)
{
//work here
}
public void t_Elapsed(object sender, ElapsedEventArgs e)
{
StartWorking();
}
Yes, you'll need another wait handle to force thread to execute. You'll basically have to WaitOne for this handle for 10 minutes, thus either elapsing a timeout or continuing whenever the wait handle becomes signalled.
Don't forget to switch that handle to a non-signalled state, though.

Categories