I want the tick event to fire every hour exactly on completion of the hour. For e.g. it should tick on 8 am then on 9 am then on 10 am etc.
It's simple that I need to set the Interval to 3600000.
The problem here is how should I identify when should I start the timer?
I'm creating a tool which will run in system tray from the time when user will log on.
Please don't create a program that does nothing but waste memory. That's what Windows' Task Scheduler is for. Run your program every hour from such a task.
http://msdn.microsoft.com/en-us/library/aa384006%28v=VS.85%29.aspx
Here's a sample:
Go to Start->Programs->Accessories->Scheduled Tasks.
On the right side, click "Add Task..".
Select your executable.
Go to the Trigger tab.
Create Trigger with the following selection:
.
Run Daily
Start today at 8:00 am
Repeat every 1 Hour
I'm sorry that I can't provide any screenshots since I'm running the german version of Windows 7.
Maybe the following code is buggy, but the idea is like this:
public void InitTimer()
{
DateTime time = DateTime.Now;
int second = time.Second;
int minute = time.Minute;
if (second != 0)
{
minute = minute > 0 ? minute-- : 59;
}
if (minute == 0 && second == 0)
{
// DoAction: in this function also set your timer interval to 3600000
}
else
{
TimeSpan span = new TimeSpan(0, 60 - minute, 60 - second);
timer.Interval = (int) span.TotalMilliseconds - 100;
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
}
void timer_Tick(object sender, EventArgs e)
{
timer.Interval = 3600000;
// DoAction
}
Per #smirkingman's suggestion, I removed 100 millisecond because of latency of project start-up and running time of the application:
timer.Interval = (int) span.TotalMilliseconds - 100;
I think it could be easier if you set up a timer every, let's say, minute, and this timer can check the system clock, when the desired time is less or equal than system time you can just run the actions (in this example with an error of 1 minute maximun)
You can improve it if you make the timer interval dinamyc, for example if you check the time and is still half an hour left you can set the interval for 15 minutes, nex time you reduce it to 5 minutoes and so on until you are checking the clock once a second, for examlpe.
HTH
Here's how I did this. The Tick event fires every 20 seconds. Simply change the minutes == "xxx" to whatever time you want the event to fire. If you need events spread out over hours, simply make the interval timer longer. Simple and effective.
private void timer1_Tick(object sender, EventArgs e)
{
DateTime Time = DateTime.Now;
int minutes = Time.Minute;
if (minutes == 00) //FIRE ON THE HOUR
{ DO THIS }
if (minutes == 15) //FIRE ON 1/4 HOUR
{ DO THIS }
if (minutes == 30) //FIRE ON 1/2 HOUR
{ DO THIS }
if (minutes == 45) //FIRE ON 3/4 HOUR
{ DO THIS }
}
Instead of firing the timer once an hour, maybe it would be more appropriate to fire the timer once a minute, and check to see if it's time yet.
The only problem with this is the worst case lag is 59 seconds. If you need it to fire exactly on the hour (at 10 am sharp), you may need to do some fiddling with the interval the first time so you line up.
Related
I'm following a tutorial on how to create a Windows Service that will send automated emails on my web server. I've got the tutorial working, however, the example code executes the service every 60mins, instead, I'd like the service executed once a day, every 24 hours, say at 9am every morning.
Below is the sample code
private Timer scheduleTimer = null;
private DateTime lastRun;
private bool flag;
public StarEmailService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("EmailSource"))
{
System.Diagnostics.EventLog.CreateEventSource("EmailSource", "EmailLog");
}
eventLogEmail.Source = "EmailSource";
eventLogEmail.Log = "EmailLog";
scheduleTimer = new Timer();
scheduleTimer.Interval = 1 * 5 * 60 * 1000;
scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed);
}
protected override void OnStart(string[] args)
{
flag = true;
lastRun = DateTime.Now;
scheduleTimer.Start();
eventLogEmail.WriteEntry("Started");
}
protected void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (flag == true)
{
ServiceEmailMethod();
lastRun = DateTime.Now;
flag = false;
}
else if (flag == false)
{
if (lastRun.Date < DateTime.Now.Date)
{
ServiceEmailMethod();
}
}
}
The line scheduleTimer.Interval = 1 * 5 * 60 * 1000; appears to be the code which sets the interval to 60mins, however, am unsure what would I need to amend this to in order to make it run every 24 hours at 9am?
Any advice would be appreciated.
Thanks.
You have couple of options:
Use Quartz .NET
Use Windows Schedule tasks
Don't rely on other timers as they will get out of sync in (near) future.
It is probably better to set your timer to smaller interval, and check the system time similar to your code does now. This code should send an email once a day on or after 9 am. The smaller your timer interval, the more accurate it will be to 9 am. For example, if you keep the timer interval at 60 minutes, the service will check the system time once an hour and the email will be sent between 9am and 10am. If you set the timer to 10 minutes, the service will check the system time once every tem minutes and send the email between 9:00 and 9:10am.
This method does not go out of sync over time, because it uses the system clock, not the timer interval to know when to fire.
Remove lastRun DateTime field and all references to it. Remove flag field and references. Add a DateTime field called nextRun:
private DateTime nextRun = DateTime.MinValue;
Add a function GetNextRun:
private static DateTime GetNextRun(DateTime lastRun)
{
var next = lastRun.AddDays(1);
return new DateTime(next.Year, next.Month, next.Day, 9, 0, 0);
}
Change ScheduleTimer Elapsed to:
protected void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (DateTime.Now < nextRun) return;
nextRun = GetNextRun(DateTime.Now);
ServiceEmailMethod();
}
So What I'm trying to do is basically.. Have 2 events, Lets called these Event 1 and Event 2, When Event 1 starts, a timer becomes activated, in which when it ends (the amount varies every time), It stores the elapsed time into a double variable
(Up to this stage it is all coded fine)
But my problem is.. I want Event 2 to run for half of the time that event 1 did.. And therefore I decided to store this value in another double variable, and setting the value divided by 2..
From here I'm wanting to then set up a sort of 'Countdown timer' So that once the amount of time has expired from the double variable with half the time stored, the event will stop.
Here is what I have so far..
//Creation of timer
Stopwatch Timer1 = new Stopwatch();
//Start the timer
Timer1.Start();
//Event 1 carries out here.. (Ain't going to bore you with this code)
//(Once ended) (ends once a condition is matched.. but cutting it short)..
//Timer1.Stop();
//Store amount in a double variable..
double dfull = Timer1.ElapsedMilliseconds;
//Half the amount in variable dhalf
double dhalf;
dhalf = dfull / 2;
//From here I want EVENT 2 to perform for the time stored in dC2B
You can do this using something like the following
System.Timers.Timer readyUpTimer = new System.Timers.Timer(100);
readyUpTimer.Elapsed -= readyUpTimer_Elapsed;
readyUpTimer.Elapsed += readyUpTimer_Elapsed;
DateTime readyUpInitialised = DateTime.Now;
readyUpTimer.Start();
Then in your event handler
void readyUpTimer_Elapsed(object sender, ElapsedEventArgs e)
{
TimeSpan elapsed = DateTime.Now - this.readyUpInitialised;
if (elapsed.TotalMilliseconds > dhalf)
{
readyUpTimer.Stop();
readyUpTimer.Dispose();
// Do other things...
}
}
I hope this helps.
Here's my problem: I have a timer that has an interval of 5 minutes. What I want is to be notified that there is only 30 seconds left on the timer so I can enable/disable certain controls (winforms in c#). I'm assuming that I would need 2 timers for this, maybe a new MyTimer class that would have these 2 timers as data members. The first timer would be for 5 minutes and the second be fore 4.5 minutes. The second timer would raise an event that I would listen to. Does anyone have any better ideas on this? Thanks for the help.
As Floris Velleman mentioned above, it would probably be best to use 1 timer that increments at a minimum time base, such as 30 seconds or even 1 second. Then use a counter and some condition statements that will react at certain times. Having 2 timers would require synchronizing between the two, which could cause some problems.
For example, with an interval of 1 second, you could do this:
int TimerInterval = 60 * 5; // 5 minutes
int NotifyTime = 30; // 30 seconds
int counter = 0;
// timer interval is set to 1 second
private void callback_MyTimer(object sender, EventArgs e)
{
counter--;
if (counter == NotifyTime)
{
// notify that 30 seconds are left...
}
// restart the counter for 5 minutes
if (counter <= 0)
{
counter = TimerInterval;
}
}
Waitable Timer objects, and the SetWaitableTimer function in particular, allow the due time and period to be controlled separately.
The MSDN documentation is here.
I'm trying to write a service in c# that should be run on a given interval (a timeout) from a given date. If the date is in the future the service should wait to start until the date time is reached.
Example:
If I set a timeout to be 1 hour from 21:00:00 I want the program to run every hour
If I set a timeout to be 1 hour from 3999.01.01 21:00:00 I want the program to until date and from then run each hour
I have sort of achieved that with the following code, but it has some problems!
When I install the service (with installutil) the service is marked as starting because of the 'Thread.Sleep()'. This service appears to be hanging and is "installing" until started.
The code inside 'ServiceTimer_Tick()' might take longer than the expected timeout. How can I prevent the timer stack from increasing if that happens?
Alternatives I've thought of :
include using the 'timeout.Interval' first time and then resetting it subsequent calls, but it doesn't feel right.
I've also considered ditching the entire service idea and compile it as a executable and set up a scheduled tasks.
Shortened example:
public Service()
{
_timeout = new TimeSpan(0,1,0,0);
_timer = new System.Timers.Timer();
_timer.Interval = _timeout.TotalMilliseconds;
_timer.Elapsed += new ElapsedEventHandler(ServiceTimer_Tick);
}
private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
lock (_obj)
{
// Stuff that could take a lot of time
}
}
public static void Main()
{
Run(new Service());
}
protected override void OnStart(string[] args)
{
long current = DateTime.Now.Ticks;
long start = new DateTime(2010,9,15,21,0,0).Ticks;
long timeout = _timeout.Ticks;
long sleep;
if (current > start)
sleep = timeout - ((current % timeout)) + (start % timeout);
else
sleep = start - current;
Thread.Sleep(new TimeSpan(sleep));
_timer.AutoReset = true;
_timer.Enabled = true;
_timer.Start();
}
This is easier with a System.Threading.Timer. You can tell it how long to wait before the first tick, and then how often to tick after that.
So, if you wanted to wait 2 days before starting, and then do something once per hour, you'd write:
Timer MyTimer = new Timer(TimerCallback, null, TimeSpan.FromHours(48), TimeSpan.FromHours(1));
That said, if this is something that only has to run once per hour, then it sounds like what you really want is an executable that you then schedule with Windows Task Scheduler.
You can use a System.Threading.Timer. It supports both a dueTime and a period which is just what you need.
you have to move the timer logic to a separate thread that you spawn from your OnStart routine. Then your logic cannot interfere with the SCM and the service will start normally.
Edit: Just to elaborate - for this task I don't think timers work very well, since you are not taking clock corrections into account which could lead to a skew (or even be incorrect if the user manually changes the clock time). That's why comparing to the clock time in small intervals is imo preferred.
The Run routine of that thread could look like this:
public void run()
{
while (processing)
{
//initiate action on every full hour
if (DateTime.Now.Second == 0 && DateTime.Now.Minute == 0)
{
//Do something here
DoSomething();
//Make sure we sleep long enough that datetime.now.second > 0
Thread.Sleep(1000);
}
Thread.Sleep(100);
}
}
I need to run a function every 5 seconds for 10 minutes.
I use a timer to run it for 5 secs, but how do I limit the timer to only 10 mins?
Just capture the time that you want to stop and end your timer from within the elapsed handler. Here's an example (note: I used a System.Threading.Timer timer. Select the appropriate timer for what you are doing. For example, you might be after a System.Windows.Forms.Timer if you are writing in Winforms.)
public class MyClass
{
System.Threading.Timer Timer;
System.DateTime StopTime;
public void Run()
{
StopTime = System.DateTime.Now.AddMinutes(10);
Timer = new System.Threading.Timer(TimerCallback, null, 0, 5000);
}
private void TimerCallback(object state)
{
if(System.DateTime.Now >= StopTime)
{
Timer.Dispose();
return;
}
// Do your work...
}
}
Have your timer loop something like this:
DateTime endTime = DateTime.Now.AddMinutes(10);
while(endTime < DateTime.Now)
{
// Process loop
}
Divide the Y minutes by the X interval to get how many times it needs to run. After that you just need to count how many times the function has been called.
In your case, 10 min = 600 seconds / 5 seconds = 120 calls needed. Just have a counter keep track of how many times your function has been called.
Timer.Stop() after 120 Ticks.
just use a DateTime variable to track when it should end and set that right before you start. The on your Elapsed event handler, check if the signal time is less than the end time. If it isn't, stop the timer.
You can calculate how times your function will be call, and create decrement counter, after elapsed which you unsubscribe from timer tick. Or you can Run another timer which have tick period - 10 min and on tick you unsubscribe from timer tick calling your function.
Note the start time. In each call, test if currentTime + 5 seconds > startTime + 10 minutes. If so, disable the timer.
I prefer this approach to just running for N ticks, as timers are not guaranteed to fire when you'd like them to. It's possible 120 ticks may run over 10 minutes of real world time.
You can set two timers one that run for 5 secs and the other one that run for 10min and disable the first one
You could use a second timer:
class Program
{
static void Main(string[] args)
{
int interval = 5 * 1000; //milliseconds
int duration = 10 * 60 * 1000; //milliseconds
intervalTimer = new System.Timers.Timer(interval);
durationTimer = new System.Timers.Timer(duration);
intervalTimer.Elapsed += new System.Timers.ElapsedEventHandler(intervalTimer_Elapsed);
durationTimer.Elapsed += new System.Timers.ElapsedEventHandler(durationTimer_Elapsed);
intervalTimer.Start();
durationTimer.Start();
}
static void durationTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
intervalTimer.Stop();
durationTimer.Stop();
}
static void intervalTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//call your method
}
private static System.Timers.Timer intervalTimer;
private static System.Timers.Timer durationTimer;
}