I'm currently writing a C# application that will schedule an event to be fired at a specific time. I started off using the Quartz library for scheduling the event, but my issue is that I need to guarantee that the event will fire within a given second, and Quartz does not offer that precision.
I could spawn a thread via Quartz a few minutes before the actual scheduled time, then just have a loop that tests if the current second is correct.
Is there a better way to do this?
Couple ways to do this:
If the application is running at all times, it can use a Timer to check if a specific time has come. If it has, it will fire the method/command to run. Here's some more basic info/tutorial on Timers: http://www.dotnetperls.com/timer
If you are wanting the event to fire when the application is not even running, you can look at creating a Task for the event you want it to perform. Link to creating a Task is here: Creating Scheduled Tasks
Related
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!
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.
I'd like to implement a recurring functionality to do something that activates, say, every Monday.
What are the ways of doing this programmatically in a Window Forms application that runs continuously in a server?
I'm familiar with delays but I haven't implemented delays that span for a week or month.
In my opinion your best bet is to write this functionality in a Console app and create a task on the server using Scheduled Tasks (or SQL Scheduler, or your favorite Scheduling tool) to execute it at whatever interval you need.
I don't like to see apps have "hidden" tasks in the code that execute at a specific time. Too many opportunities to fail without notification.
With a scheduling tool you can view/change the schedule without having to touch source code.
As side notes, Windows Forms apps should run on the client, not on the server.
If you're app is already running anyways, what I would do is have a periodic task that checks whether you want to do your weekly task
here's psudocode to demonstrate the logic.
if(today is Monday && i didn't do this task yet today)
{
//do monday stuff
}
Ideally you should perform this operation under windows scheduled task. It will then take care of the recoccurrance as well as timing.
If you need to do this via a winforms application, then there are two options - periodic time polling or blocking wait/sleep.
With periodic time polling, you set a time interval in which the application must run. Then in a loop check if this period has elapsed, and take action. You can set the required level of accuracy in side the loop.
With blocking wait, you sleep the running thread until it is time to execute. The only issue with this approach is if the server restarts, the application should regain it's state and resume any sleep operations. The accuracy of this approach should be within a few seconds (depending on the time drift of your server).
I m able to build a windows service and install it.
I m curious how can i run this service every hour ? I want it to run every hour periodically.
I also need to know the hour range that it s running so that I can store it somewhere.
How can i do that?
Edit : This service will be installed on many machines, therefore, I dont want to create a scheduled task say on 100 servers.
If you want a task to run on a regular interval as opposed to constantly, you should look into using the Task Scheduler.
If you need your code to be a service, but to be "activated" every hour, the easiest approach would be to make your service a COM object and have a simple task scheduled every hour that invokes a jscript/vbscript that creates your COM object and calls simple method on it.
The alternative is to use any of the wait APIs to "waste" an hour without consuming cycles.
Note that you also have to consider some interesting design decisions that depend on what your scenario is:
how is your service going to be started if it crashes or is stopped by the user?
if you are started after more than an hour, should you run again or do you need to wait to get on the exact hourly schedule?
how do you keep track of the last "activation" time if the timezone or the day-light saving time has changed while you were not active?
does your service prevent the computer from going to sleep/hibernate on idling or when the laptop cover is closed? if not, do you need to awake the computer on the hour to get your service working on your schedule?
Some of those are taken care of by the task scheduler, so I would strongly recommend going that route vs. waiting for an hour in your code.
You could create a scheduled task that runs every hour, to either run the service or send a message to "wake it up". Then, either pass in the current time in the scheduled task request, or just have your program pick up the current time when it wakes up.
Task Scheduler Managed Wrapper can help you set this up programmatically; you can google for other resources as well.
There are a couple options.
You could sleep for an hour.
You might be better suited for a Scheduled Task, not a service.
Thread.Sleep(1000*60*60);
Thread.Sleep(TimeSpan.FromHours(1));
code more readable this way
Thread.Sleep() solution will make sure that your service will run in one hour intervals, not every hour i.e. each task will be started at 1 hour + time to run the task. Consider using a Timer within your service. This will be a more robust solution since you have a control when to run a task, monitor its progress etc. Just remember that each Timer event will be fired in a different thread and if the task takes longer than one hour to run you might have to wait for the first task to finish to avoid concurrent tasks.
Task schedulers may be a good idea but services are designed to do this. Services gets installed easily and logs things properly. All you need to do is, at start of service, you can install a system timer (System.Threading.Timer) or there is also one more timer.
How can I write a scheduler application in C# .NET?
You could also try Quartz.Net.
It all depends on your requirements:
If you have access to a database you use a table as a queue and a service to poll the queue at regular intervals.
If your application is client only (CLI) you can use the system scheduler ("Scheduled Tasks").
Lastly, if your application is only in a database (using the CLR in SQL Server 2005 for example) then you can create a SQL Server job to schedule it.
Assuming you're writing some system that needs to perform an action at a specific clock time, the following would cover the fundamental task of raising an event.
Create a System.Timer for each event to be scheduled (wrap in an object that contains the parameters for the event). Set the timer by calculating the milliseconds until the event is supposed to happen. EG:
// Set event to occur on October 1st, 2008 at 12:30pm.
DateTime eventStarts = new DateTime(2008,10,1,12,30,00);
Timer timer = new Timer((eventStarts - DateTime.Now).TotalMilliseconds);
Since you didn't go into detail, the rest would be up to you; handle the timer.Elapsed event to do what you want, and write the application as a Windows Service or standalone or whatever.
Write a windows service, there are excellent help topics on MSDN about what you need to do in order to make it installable etc.
Next, add a timer to your project. Not a Winforms timer, those don't work in Windows Services. You'll notice this when the events don't fire. Figure out what your required timer resolution is - in other words, if you have something scheduled to start at midnight, is it Ok if it starts sometime between Midnight and 12:15AM? In production you'll set your timer to fire every X minutes, where X is whatever you can afford.
Finally, when I do this I use a Switch statement and an enum to make a state machine, which has states like "Starting", "Fatal Error", "Timer Elapsed / scan for work to do", and "Working". (I divide the above X by two, since it takes two Xs to actually do work.)
That may not be the best way of doing it, but I've done it that way a couple of times now and it has worked for me.
You can try use Windows Task Scheduler API
You can also use the timer control to have the program fire of whatever event you want every X ticks, or even just one. The best solution really depends on what you're tring to accomplish though.