Windows Service needs to wait, Thread.Sleep? - c#

I have a c# windows service that needs to execute a database query every 60 seconds (or whatever interval is set in the config file). I'm using Thread.sleep(60) in a while loop to accomplish this. Is there a better way to do this?
Thanks

You can use a System.Threading.Timer to run your code every 60 seconds instead of doing it in a sleeping thread.

It depends on what you want to do. If you want a (more) exact method you may want to use System.Threading.Timer. One thing about thread.sleep is that it really is "sleepatleastuntil...". The processor will ignore your thread until the sleep time is past. The next time it would give your thread priority, after the sleep time is past, it will.
This will normally be very close to the desired interval, but could be longer. Don't yield unless you really intend to yield.

Use a Timer to fire the process every 60 seconds rather than force the process to sleep.

Related

.NET Scheduling many operations: single timer vs one timer for operation

I am developing a Windows Service application, in .NET, which executes many functions (it is a WCF service host), and one of the targets is running scheduled tasks.
I chose to create a System.Threading.Timer for every operation, with a dueTime set to the next execution and no period to avoid reentrancy.
Every time the operation ends, it changes the dueTime to match the next scheduled execution.
Most of the operations are scheduled to run every minute, not all toghether but delayed by some seconds each other.
Now, after adding a number of operations, about 30, it seems that the timers start to be inaccurate, starting the operations many seconds late, or even minutes late.
I am running the operation logic directly in the callback method of the timer, so the running thread should be the same as the timer.
Should I create a Task to run the operation instead of running it in the callback method to improve accuracy?
Or should I use a single timer with a fixed (1 second) dueTime to check which operations need to be started?
I don't like this last option because it would be more difficult to handle reentrancy..
Timers fire on a thread pool thread, so you are probably finding that as you add lots of timers that you are exhausting the thread pool.
You could increase the size of the thread pool, or alternatively ensure you have fewer timers than the thread pool size.
Firing off Tasks from the callback likely won't help - since you are going to be fighting for threads from the same thread pool. Unless you use long-running tasks.
We usually setup multiple timers to handle different actions within a single service. We set the intervals and start, stop the timer on the Service Start/Stop/Shutdown events (and have a variable indicating the status for each one, i.e. bool Stopped)
When the timer ticks over, we stop the timer, run the processing (which may take a while depending on the process, i.e. may take longer than the interval if its short.. (this code needs to be in a try--catch so it keeps going on errors)
After the code has processed, we check the Stopped variable and if its not stopped we start the timer again (this handles the reentrancy that you've mentioned and allows the code to stick to the interval as much as possible)
Timers are generally more accurate after about 100ms as far as I know, but should be close enough for what you want to do.
We have run this concept for years, and it hasn't let us down.
If you running these tasks as a sub-system of an ASP.NET app, you should also look at HangFire, which can handle background processing, eliminating the need for the windows service.
How accurate do the timers need to be? you could always use a single timer and run multiple processing threads at the same time? or queue the calls to some operations if less critical.
Ok, I came to a decision: since I am not able to easily reproduce the behavior, I chose to solve the root problem and use the Service process to only:
serve WCF requests done by clients
schedule operations (which was problematic)
Every operation that could eat CPU is executed by another process, which is controlled directly by the main process (with System.Diagnostics.Process and its events) and communicates with it through WCF.
When I start the secondary process, I pass to it the PID of the main process through command line. If the latter gets killed, the Process.Exited event fires, and I can close the child process too.
This way the main service usually doesn't use much CPU time, and is free to schedule happily without delays.
Thanks to all who gave me some advices!

Issue regarding Thread.Sleep() for 2hours in c#

I am working on .net windows application.
I am using System.Threading.Thread.
In a single form using five(5) threads. I have a code which when run, it executes series of lines in sequence. I would like to add a pause in between.
For that i am using
Thread.Sleep(10800000)
of 3 hours
But I checked in debug mode, after executing line of
Thread.Sleep(10800000)
My debug not goes to next line or next line never executes even after waiting for 4 hours.
I am using this Thread.Delay in other thread not in main thread.
This delay requires because, i send a command to configure setting to a hardware, that setting requires minimum 3 hours to complete.
That's why i am using this
Thread.Delay(10800000)
Means my onward code is proceed only after waiting for 3 hours.
Can any one help me?
Thread.Sleep is not designed for long sleeps. You should consider using somthing like System.Threading.Timer.
Provides a mechanism for executing a method on a thread pool thread at specified intervals.
You can give it a first run time of midnight, and have it go off every 24 hours. the Timer(TimerCallback, Object, TimeSpan, TimeSpan) constructor is exactly what you are looking for.
One would argue that even using a timer is not the best tool for the job. You may want to consider using Windows Task Scheduler (TS) instead. With TS, you can setup a schedule to say run your app and carry out the workflow, or if your program must run all the time, trigger another process that communicates with your app somehow.
If the process is not doing anything until the next interval then it's best to just simply kill the app. That way you won't be wasting threads or processes twiddling their thumbs over exorbitant delays waiting for the next interval to do something.
You can use the Microsoft Task Scheduler v2 COM Library from c# to setup your schedules or do so manually from the TS UI itself.

How to add actual wait?

Im currently trying to code very simple thing.
what it supposed to do:
enter google
wait 5 seconds
search something.
now, the part I cant do is wait.
There is thread sleep etc. but they stop GUI and makes my program unusable.
I can also do it with timers but it isnt very effective way to do it, since in actual app there will be many waits...
Are there anyway to do with it like 2-3 lines of code only, and without stopping GUI?
A timer is exactly what you want here - you want to say, "In 5 seconds, do X" (potentially executing in the UI thread) which is exactly what a timer does for you. If you want to encapsulate that in a single method which you can pass in an Action and a TimeSpan or whatever, that's fine - but a timer is definitely the way to go.
(The type of timer you want to use will depend on what thread you want the timer to fire on, etc.)
You need to do the work on a seprate thread so it dosent halt the GUI thread.
Thread worker = new Thread(dowork);
worker.Start();

time or timing in C#, and another question

the question is:
how can i for example every two seconds without user intervention make a label flashes.
like every 2 seconds label.text="". and the next two seconds i do this label1.text="visible"
or changing another property like color or anything.
i give up
could you help me with a basic code, thank you.
You may try using the timer with a 2-second interval. But keep in mind, whenever you play with threads outside of the UI, you need to look in to delegates and BeginInvoke
To accomplish what you're after, you could run it every 1 second, then check against DateTime.Now to see if the clock matches your criteria.
Your question is a bit difficult to understand, but I'll give it my best shot.
From what I understand, you want your code to do something every two seconds. The easiest way to do that is with a timer. The System.Timers.Timer class is useful for that, as well as System.Threading.Timer. Which you use is up to you, but the one in the Threading namespace is a little more primitive.
Timers operate on a ThreadPool, so if you will be manipulating a Windows Form, make sure what you do happens on the GUI thread either by using Control.Invoke for Windows Forms or Dispatcher.Invoke for WPF. Timers are also a little tricky because their Threading Apartment is typically MTA, so if you try to access the clipboard or something like that, you may get errors.
If you want to ensure your timer fires exactly at a certain time, rather than at a specific interval, you could make a timer with a period that starts another timer, or adjusts itself. I would argue that if you are doing something every 2 or 5 seconds do you really need it to happen at a very specific time? Timers, and Windows Time in general isn't specific enough and has small inaccuracies - it will drift over time by a few milliseconds.
What you could do with one thread is something like this :
Sleep 2 seconds
DoAction
Sleep 2 seconds
DoAnotherAction
In a loop.
With 2 threads, I would recommend something like this : C# Running timed job on StackOverflow
Edit : use QuartzNet (tutorial).
A link on StackOverFlow.
The easiest way to do this is with System.Windows.Forms.Timer. You can drop it on your form and set the interval, and create the Tick event handler. The linked documentation has a simple example that you can easily modify to work with your label.
The beauty of using this timer is that it automatically synchronizes with the UI thread, so you don't have to worry about Invoke, BeginInvoke, etc.

How to trigger an event at 03:00 every night?

How is this done best? I want an app that's running on a server to trigger an event every night at 03:00.
Use windows task scheduler
If you want to do this in running app code (instead of using a task scheduler), you should choose a duration to let your app sleep that's fairly long (e.g., 1 hour, or 3,600 sec). Your app loops, and as each sleep call expires, the app periodically checks how much time is left until the deadline time (03:00). Once the remaining sleep time gets below the coarse interval time, it should be reduced to a shorter interval (halved each time, or reduced to 10 sec). Continue the loop, sleeping and reducing the interval time, until the target deadline time is reached.
This prevents the loop from waking up too often (86,400 1-sec intervals is overkill), but it also prevents the app loop from overshooting the target deadline time by sleeping too long.
You could make a timer with an interval of 1 second and when the timer goes off, check if it's 3:00.
You'll need to build it in a service in order to ensure that it runs even if there's nobody logged into the machine, and then there are lots of different methods to ensure that the trigger occurs.
Consider making a System.Timers.Timer where the Interval is set to the difference between DateTime.Now and the next 3:00.
There are two basic options here.
If you're trying to do this within an existing service, you can use a Timer to trigger yourself at 3:00 each night, and run your "task".
That being said, this is typically better handled via Windows Task Scheduler. Instead of keeping the application alive 24/7, you just schedule it to run once every day at 3:00.
Edit:
If you need to work with the Task Scheduler from code (mentioned in another comment), that is also possible. The Task Scheduler provides an API for setting up individual Tasks (ITask) via the Task scheduler (ITaskScheduler).
However, given that you're working on XP Embedded, you're probably better off just using the normal system configuration capabilities, and setting up a task to run once each day. In an embedded system, you should have enough control during your deployment to do this.
Here is a simplified version of a service that we wrote that runs a timer every 60 seconds to watch a table... you could alter the timer elapse event to check the time and run it then:
Dim Timer As System.Timers.Timer
Protected Overrides Sub OnStart(ByVal args() As String)
Timer = New System.Timers.Timer(60000)
AddHandler Timer.Elapsed, AddressOf timer_Elapsed
Timer.Start()
End Sub
Protected Overrides Sub OnStop()
Timer2.Stop()
End Sub
Private Sub timer_Elapsed(ByVal pSender As Object, ByVal pargs As System.Timers.ElapsedEventArgs)
'Ensure the tick happens in the middle of the minute
If DateTime.Now.Second < 25 Then
Timer.Interval = 65000
ElseIf DateTime.Now.Second > 35 Then
Timer.Interval = 55000
ElseIf DateTime.Now.Second >= 25 And DateTime.Now.Second <= 35 Then
Timer.Interval = 60000
End If
'Logic goes here
End Sub
Obviously, if you can, use the task scheduler like everyone else here has mentioned. It is the preferred way of doing this. I just happened to have this code laying around so I thought I'd post it in case it could be helpful to you. Also, this code worked for us because we never knew when an external source was going to edit a table. Setting the interval to a correct number of milliseconds would be a much more efficient way of doing this, as pointed out by md5sum.
This answer might be a bit left field, but we often use CruiseControl.NET for some of our scheduled tasks. It's not perfect for them all, but if it's a big job that you want to run every night and other code/outcomes depend on it then it's a good choice. You can schedule it to run whenever, get emails if it worked/failed. Run other scripts/code if it did not work, clean up files you need before you start and after.
Not the perfect solution to all situation, but it is damn powerful for those that call for it. We use it for some of our big data processing jobs, and it sends us all an email if it worked/failed and will even try again 30 minutes later if it failed the first time. It gives you a nice fuzzy feeling :)
Windows task scheduler (as suggested by klausbyskov) or a SQL Server job.
EDIT:
Or if you want a dyanically assigned time, you could create a windows service that polls every 10 minutes and performs some action at the desired time(s).
Creating a windows server in C# is fairly trivial and could do this. Just make sure you've got the security and logging figured out because it can be pretty hard to tell what's going on while it is (or isn't) running.
Use System.Threading.Timer.
I'm spawning a thread in an ASP.NET application to do scheduled tasks.
It depends on what you have available to you.
Your best bet is to use a cron job, if you are on Linux/Unix/Mac OS X, a task scheduler on Windows, or launchd on newer versions of Mac OS X.
If you want to do this from within an application, you would need a loop that checks the time on a regular basis and fires off the event if it is 03:00, but this isn't ideal.
Is the program able to run via command line? If so, create a foo.bat file, and call your program command line (very simple).
Then use Task Scheduler to run the .bat file at 3 a.m. daily.

Categories

Resources