Adjustable service timer in C# - c#

I'm trying to write a Windows service that runs indefinitely. Windows forms and background programs for Linux don't seem too bad but maybe I'm just horribly inept at Windows Services. Unlike some other sleep or timer related questions I've dug through here, the time to wake up or sleep can be a regular interval, but isn't always such. The program reads from some data files that may instruct it to change its own schedule and this must take effect as of its next wake up time. It seemed quite easy as a console program and behaved perfectly there:
while (true)
{
// Calculate next time to run.
DateTime nextRun = NextWakeup();
TimeSpan nextTime = nextRun - DateTime.Now;
int sleepMs = (int)nextTime.TotalMilliseconds;
// Sleep until scheduled time
System.Threading.Thread.Sleep(sleepMs);
// Do a code cycle of more stuff here...
}
However, when I try to run it as part of a service so that it continues to be active while the user is logged out, the Service Manager stubbornly refuses to start it. I get the lovely 1053 error, "The service did not respond to the start or control request in a timely fashion."
A lot of answers to related questions here seem to suggest going with a timer at all costs over thread sleeping. If I did such a thing instead of the while/sleep combination, how would I go about changing the timer interval at each run? Or is this all perfectly fine and I'm going about setting up my service wrong?
Much thanks in advance!

Windows services must usually respond to a control request (ususally start/stop but also pause/resume) in 30seconds. This means that if you sleep the main thread in the OnStart your service will return the error you refer to.
The way to resolve your issue is to do your work on a separate thread, where you're free to sleep the thread in the way you describe. Just start this thread in the services' OnStart and you should be able to easily return within the 30 second limit.
As an aside, instead of while(true) you should consider the service being stopped must also return in that 30 second limit. If you have a thread sat sleeping the service will not shut down properly without either Aborting the thread (bad) or providing some mechanism for properly exiting the thread. This is exactly why most people go with the polling approach; the service can both determine whether its time to run, or determine whether a stop request has taken place. As long as this poll freqency is <30s the service will always shut down properly.

If you want to use timers its quite easy to do. I'd use System.Timers.Timer and changing its interval is as easy as mytimer.Inverval = nextTime.Seconds or similar.
I'd personally run the timer without AutoReset = false (so it doesn't restart the timer automatically) and then every time it wakes up it runs your "dowork" and then at the end of the dowork you work out when you want it to run next, set the interval as appropriate and then call Start on your timer again.
Of course in your service your start method just sets up the first timer run and then returns so that the startup is nice and quick. On shutdown you just clean up your timer (stop and dispose and such like) and then just return. Nice and clean.

I think you might be looking for something like this:
static class ConsoleProgram
{
static void Main()
{
ServiceBase[] servicesToRun = new ServiceBase[] { new MyService(config, Logger) };
ServiceBase.Run(servicesToRun);
}
}
public partial class MyService : ServiceBase
{
private bool _stopped = true;
protected override void OnStart(string[] args)
{
StartTimer();
}
protected override void OnStop()
{
StopTimer();
}
public void StartTimer()
{
_stopped = false;
Timer t = new Timer(TimerProc);
// Calculate your desired interval here.
t.Change(_config.Interval, new TimeSpan(0, 0, 0, 0, -1));
}
public void StopTimer()
{
_stopped = true;
}
private void TimerProc(object state)
{
// The state object is the Timer object.
Timer t = (Timer) state;
t.Dispose();
ThreadPool.QueueUserWorkItem(DoWork);
if (!_stopped) {
StartTimer();
}
}
}

Related

How to create an application loop in C#

I have a console server in C# that keeps running in a while(true) loop. But that takes > 50% CPU even if it is doing nothing. I tried Thread.Sleep it worked! Not eating my CPU anymore but, it do not resumes in the exact time specified and is not considered good practice. Am I doing the right thing? Or is there any other way than using while(true) and Thread.Sleep?
When you want to suspend thread for a while without consuming CPU resources, you usually use some WaitHandle (such as AutoResetEvent or ManualResetEvent) and call it's WaitOne() method to suspend thread until event that is supposed to wake it up occurs (e.g. key is pressed, new network connection arrives, asynchronous operation finishes, etc.).
To wake up thread periodically, you can use timer. I'm not aware of any timer in .NET Framework, that provides WaitHandle (of course you can easily create such class yourself), so have to use Timer and call AutoResetEvent.Set() manually on each tick in it's callback.
private static AutoResetEvent TimerWaitHandle = new AutoResetEvent(false);
static void Main()
{
// Initialize timer
var timerPeriod = TimeSpan.FromMilliseconds(500);
Timer timer = new Timer(TimerCallback, null, timerPeriod, timerPeriod);
while(true)
{
// Here perform your game logic
// Suspend main thread until next timer's tick
TimerWaitHandle.WaitOne();
// It is sometimes useful to wake up thread by more than event,
// for example when new user connects etc. WaitHandle.WaitAny()
// allows you to wake up thread by any event, whichever occurs first.
//WaitHandle.WaitAny(new[] { TimerWaitHandle, tcpListener.BeginAcceptSocket(...).AsyncWaitHandle });
}
}
static void TimerCallback(Object state)
{
// If possible, you can perform desired game logic here, but if you
// need to handle it on main thread, wake it using TimerWaitHandle.Set()
TimerWaitHandle.Set();
}
I can't comment, so i'll put it here.
Theorically with Thread.sleep(1) it won't use that much CPU.
You can get more info from this question/answer: What is the impact of Thread.Sleep(1) in C#?
You can use System.Threading.Timer class. It Provides a mechanism for executing a method on a thread pool thread at specified intervals.
Example
public void Start()
{
}
int dueTime = 1000;
int periodTS = 5000;
System.Threading.Timer myTimer = new System.Threading.Timer(new TimerCallback(Start), null, dueTime, periodTS);
This will call start method after 1 second from calling it and after that start will be called after every 5 second.
You can read more about Timer class here.

how to set timer for each different thread in window service

trying to set timer for each different threads with different timings , as far as i know if we set a timer in main method the same will works for all the threads, so i want to know how to set timer for each different thread with out killing the threads, kindly advice on this please
static Timer _timer;
static void Main(string[] args)
{
_timer = new Timer(10000);
_timer.Enabled = true;
_timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
the above pasted code will do job for all of the threads will run for every ten sec, how ever all threads will run for every ten sec by the timer in main method, my concern is have to set timer for each thread with different timing
Summary:
why i asked like this question, here i have requirement of window service,what is to do means,For example in a window service having a three different threads(XYZ,ABC,PQR), if i start a service,all the three threads to be intialized and those threads should to be acts as For which based on timer settings which we are passing from the app config,these thread has to be fire based on the timings has setted,kindly advice
If you want to start some threads after a given time, you can use System.Threading.Timer.
int[] times = new int[] { 10000, 14000, 17000 };
foreach (int time in times)
{
System.Threading.Timer t = new System.Threading.Timer(MyTimerCallback, null, time, 0);
...
}
private void MyTimerCallback(object state)
{
//Do some awesome stuff
}
Have you tried to use the [ThreadStatic] attribute?
This attribute defines that the veriable it coupled with will not be shared between threads, and a copy of him will be created for each thread.
[ThreadStatic]
static Timer _timer;
void MyThreadStartMethod()
{
_timer=new Timer(value);
...
}
And also, i don't see any threads in your code. The Main method is called by the CLR to start the application, and runs each time in a different process.

System.Timers.Timer delay hangs application

I have an issue with the System.Timers.Timer object. I use the timer object to perform a task at regular intervals. In the timer constructor I call the method doing the work ( DoTimeCheck() ), to ensure that the task is run once at startup also. The work (at regular intervals) is done in a BackgroundWorker.
I call the timer with this:
UpdaterTimer ut = UpdaterTimer.UpdaterTimerInstance;
My problem is that I need to delay the first run of the task with 3 minutes(the one that runs at application startup). Subsequent runs (Elapsed event) should run without delay. I thought of doing this by calling
System.Threading.Thread.Sleep(TimeToDelayFirstRunInMiliseconds);
but this fails, because it also hangs the UI of the app (main thread) making it unusable. How can I delay the first run of DoTimeCheck() without hanging the UI?
The code of the timer is below. If the issue is not presented in a clear manner please let me know and I will edit. Thank you in advance.
public sealed class UpdaterTimer : Timer
{
private static readonly UpdaterTimer _timer = new UpdaterTimer();
public static UpdaterTimer UpdaterTimerInstance
{
get { return _timer; }
}
static UpdaterTimer()
{
_timer.AutoReset = true;
_timer.Interval = Utils.TimeBetweenChecksInMiliseconds;
_timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
_timer.Start();
DoTimeCheck();
}
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
DoTimeCheck();
}
private static void DoTimeCheck()
{
//... work here
}
}
One way of doing this would be to give the Timer Interval an initial value (e.g. 3 minutes). Then, in your Elapsed event handler, you could change the interval to your regular value which will be used from then on.
_timer.Interval = Utils.InitialCheckInterval;
static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (_timer.Interval == Utils.InitialCheckInterval)
{
_timer.Interval = Utils.RegularCheckInterval;
}
DoTimeCheck();
}
It appears (although you've not shown that code) that you're calling Sleep(TimeToDelayFirstRunInMiliseconds); on the main/GUI thread, so that's what's causing your UI thread to hang. Instead, you should set your timer to be delayed by 3 minutes on the first run, then once it runs you change the timer again to run at the frequency you desire for all the subsequent runs.
Your UI resides on the same thread, so when you put the thread to sleep, it will cause your UI to hang as well. You need to run the timer on a different thread.
You're already using timers fine it seems. Just use another one to do a three minute delay before you start up your other timer.
timer = new Timer();
timer.AutoReset = false;
timer.Interval = 3*60*1000;
timer.Elapsed += startOtherTimerMethod;
timer.Start();
Edit: I should note that this is much the same as Peter Kelly's answer except that his solution is more elegant since it uses just one timer, no extra methods and takes advantage of the fact that the timer is changeable between runs. If you liked this answer, you'll love his. ;-)
Your UI needs a seperate thread, currently you are also sleeping the UI. Check this post.
You should not use thread.sleep in this situation you should use the winforms control
BackgroundWorker which never locks the main UI. You can write your logic there.
example here:
http://www.knowdotnet.com/articles/backgroundworker.html
Use a System.Threading.Timer - the constructor takes a parameter for the delay of the first run and an interval for the subsequent runs.

Windows service scheduled execution

If I have a Windows Service that needs to execute a task every 30 seconds which is better to use; the Timer() class or a loop that executes the task then sleeps for a number of seconds?
class MessageReceiver
{
public MessageReceiver()
{
}
public void CommencePolling()
{
while (true)
{
try
{
this.ExecuteTask();
System.Threading.Thread.Sleep(30000);
}
catch (Exception)
{
// log the exception
}
}
}
public void ExecutedTask()
{
// do stuff
}
}
class MessageReceiver
{
public MessageReceiver()
{
}
public void CommencePolling()
{
var timer = new Timer()
{
AutoReset = true,
Interval = 30000,
Enabled = true
};
timer.Elapsed += Timer_Tick;
}
public void Timer_Tick(object sender, ElapsedEventArgs args)
{
try
{
// do stuff
}
catch (Exception)
{
// log the exception
}
}
}
The windows service will create an instance of the MessageReciever class and execute the CommencePolling method on a new thread.
I think it really depends on your requirement.
case 1.
Suppose you want to run this.ExecuteTask() every five minutes starting from 12:00AM (i.e., 12:00, 12:05, ...) and suppose the execution time of this.ExecuteTask() varies (for example, from 30 sec to 2 min), maybe using timer instead of Thread.Sleep() seems to be an easier way of doing it (at least for me).
However, you can achieve this behavior with Thread.Sleep() as well by calculating the offset while taking timestamps on a thread wake-up and on a completion of this.ExecuteTask().
case 2.
Suppose you want to perform the task in the next 5 min just after completion of this.ExecuteTask(), using Thread.Sleep() seems to be easier. Again, you can achieve this behavior with a timer as well by reseting the timer every time while calculating offsets on every time this.ExecuteTask() completes.
Note1, for the case 1, you should be very careful in the following scenario: what if this.ExecuteTask() sometimes takes more than the period (i.e. it starts at 12:05 and completes 12:13 in the example above).
What does this mean to your application and how will it be handled?
a. Total failure - abort the service or abort the current(12:05) execution at 12:10 and launch 12:10 execution.
b. Not a big deal (skip 12:10 one and run this.ExecuteTask() at 12:15).
c. Not a big deal, but need to launch 12:10 execution immediately after 12:05 task finishes (what if it keeps taking more than 5 min??).
d. Need to launch 12:10 execution even though 12:05 execution is currently running.
e. anything else?
For the policy you select above, does your choice of implementation (either timer or Thread.Sleep()) easy to support your policy?
Note2. There are several timers you can use in .NET. Please see the following document (even though it's bit aged, but it seems to be a good start): Comparing the Timer Classes in the .NET Framework Class Library
Are you doing anything else during that ten second wait? Using Thread.sleep would block, preventing you from doing other things. From a performance point of view I don't think you'd see too much difference, but I would avoid using Thread.sleep myself.
There are three timers to choose from - System.Windows.Forms.Timer is implemented on the main thread whereas System.Timers.Timer and System.Threading.Timer are creating seperate threads.
I believe both methods are equivalent. There will be a thread either way: either because you create one, or because the library implementing the Timer class creates one.
Using the Timer class might be slightly more less expensive resource-wise, since the thread implementing timers probably monitors other timeouts as well.
I this the answers to this question will help.
Not answered by me but John Saunders (above)... the answer can be found here For a windows service, which is better, a wait-spin or a timer?

Creating a Loop to Pause a Script While a Callback Function Operates

I am currently using a third party component to handle telnet connections in .NET. I want it to be synchronous where I send a command to the receiving telnet server and then I get the response back as text or byte array. Only problem is that the component is not set up to do that. The component allows me to send commands to the server, but the response is returned via a function handle. So in essence, I need a way to pause the application while the handler does it's processing. Here is an example of how I plan to get around that issue:
static void Main(string[] args)
{
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
while (true) ;
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
string responseStr = e.Text;
if (responseStr.Contains("Username:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(username));
}
else if (responseStr.Contains("Password:"))
{
((Telnet)sender).Send(System.Text.ASCIIEncoding.ASCII.GetBytes(password));
}
}
The solution above will not work since the while will always run, but I will probably build a future version that uses some sort of global variable to track if the loop still needs to run. However, everything I have been taught about programming says this is very dirty. Can anyone think of another way around my dilemma?
Thanks,
Chris
Here is an example of using a ManualResetEvent to suspend execution (and delay program end) until your event handler says it's finished.
static ManualResetEvent finishGate;
static void Main(string[] args)
{
finishGate = new ManualResetEvent(false); // initial state unsignaled
Telnet telCon = new Telnet();
telCon.OnDataIn += new Telnet.OnDataInHandler(HandleDataIn);
telCon.Connect(remoteHostStr);
finishGate.WaitOne(); // waits until the gate is signaled
}
public static void HandleDataIn(object sender, TelnetDataInEventArgs e)
{
// handle event
if (processingComplete)
finishGate.Set(); // signals the gate
}
The WaitOne() method of ManualResetEvent also includes overrides that accept a timespan or number of milliseconds. It returns bool - true if it was signaled, false if it timed out. If you put that in a loop, you could have your main thread wake up every 30 seconds and perform some housekeeping tasks, but still have an instantaneous response when the gate is signaled.
Your while loop:
while(true) ;
will drive CPU usage to 100% (well, 100% of 1 core on a multicore machine) and leave it there, permanently.
This will starve other processes of CPU power, and may prevent the Telnet component from working at all because you've bypassed the message pump.
There are better ways, but without more information on what you're doing, it will be hard to advise you.
To begin, do you want a WindowsForms/WPF/Console application?
[And please, use comments to answer, not Answers.]
In general, when you really need to wait, use a WaitHandle. In this case, a ManualResetEvent would probably be what you need.
A better way would be to spawn the Telnet processing to another thread. That way you can get the main thread to wait for the telnet processing to complete.
Have a look here for some very good tutorials on threading.

Categories