C# Timer Interval Every 24 Hours - c#

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

Related

Can I change a timer's interval without resetting it?

I have a timer that is supposed to generate a Console.Beep at the rate of my Heart Rate in beats/minute. I am using the following simple formula to calculate the Timer.Interval in my C# timer:
ServerVarValues = new ws ServerVarValues();
this.timerHeartBeatSound = new System.Windows.Forms.Timer(this.components);
public class ServerVarValues
{
public int HR;
public DateTime LastHRUpdate;
public int SpO2;
public DateTime LastO2Update;
public double Temperature;
public DateTime LastTempUpdate;
}
//... I plug in my heart rate to calculate my new timer interval...
int tVal = (int)Math.Round((ws.HR / 60.0) * 1000,0);
timerHeartBeatSound.Interval = tVal;
// and with the new interval, the timer generates a Tick Event that runs this
private void PlayHeartBeatSound(object sender, EventArgs e)
{
Console.Beep();
}
I am reading my heart rate from a wearable. The problem is that every time that my HR changes, the timer is reset when I change the timer's interval. Thus, I hear hiccups often instead of a smooth changing heart rate sound.
Any ideas on how to avoid resetting the timer every time the heart rate changes?
Yes, this is by design. When you change the Interval property, and it is not the same, then the Timer resets itself. You cannot alter this behavior.
So what you must do is not update Interval. Not until the next Tick happens. Which is fine, the heart-beats happen quickly enough. You'll need another variable:
public class ServerVarValues {
public int NextInterval;
// etc...
}
And initialize it when you start the timer or update the heart-rate value:
...
int tVal = (int)Math.Round((ws.HR / 60.0) * 1000,0);
if (timerHeartBeatSound.Enabled) ws.NextInterval = tval;
else {
ws.NextInterval = 0;
timerHeartBeatSound.Interval = tval;
}
And in the Tick event handler you need to check if you have to make the new interval effective:
private void PlayHeartBeatSound(object sender, EventArgs e)
{
if (ws.NextInterval != 0) timerHeartBeatSound.Interval = ws.NextInterval;
ws.NextInterval = 0;
Console.Beep();
}
Try the following, except instead of "ASecond" use the number of milliseconds corresponding to the current heart rate. This will recalculate the number of milliseconds until the next beat, based on the current rate and do it for every beat. I hope it is smoother.
DateTime LastTime = DateTime.Now;
...
DateTime NextTime = LastTime + ASecond;
// Just in case we have gone past the next time (perhaps you put the system to sleep?)
if (DateTime.Now > NextTime)
NextTime = DateTime.Now + ASecond;
TimeSpan Duration = NextTime - DateTime.Now;
LastTime = NextTime;
timer1.Interval = (int)Duration.TotalMilliseconds;

Reset the count of inactive time in C#

I found this post and created a class that used it to detect inactive time and it works great. I set it for one minute and after one minute I can get it to "do stuff". What I am trying to do is only do something every "x" minutes of inactive time; i.e. every 5 minutes do this if things have been inactive and do not repeat again 'til X time has elapsed.
Now, I could set my timer to fire every 5 minutes instead of every second, but I would like to be able to "reset" the count of inactive time instead. Any suggestions?
This is for using the DispatchTimer in C# and WPF.
Just create a class level variable, increment it on your timer, and reset it when you get activity. Create a timer, say tmrDelay with an increment of 10000 milliseconds, and a button, btnActivity to reset the count, and do this:
private int tickCount = 0;
private const int tick_wait = 30;
private void tmrDelay_Tick(object sender, EventArgs e)
{
tickCount++;
if (tickCount > tick_wait)
{
DoSomething();
tickCount = 0;
}
}
private void btnActivity_Click(object sender, EventArgs e)
{
tickCount = 0;
}
It sounds like you want something like the following:
static DispatcherTimer dt = new DispatcherTimer();
static LastInput()
{
dt.Tick += dt_Tick;
}
static void dt_Tick(object sender, EventArgs e)
{
var timer = (DispatcherTimer)sender;
var timeSinceInput = TimeSpan.FromTicks(GetLastInputTime());
if (timeSinceInput < TimeSpan.FromMinutes(5))
{
timer.Interval = TimeSpan.FromMinutes(5) - timeSinceInput;
}
else
{
timer.Interval = TimeSpan.FromMinutes(5);
//Do stuff here
}
}
This will poll every 5 minutes to see if the system has been idle for 5 minutes or more. If it's been idle for less than 5 minutes it will adjust the time so that it will go off again at exactly the 5 minute mark. Obviously then if there has been activity since the timer was set it will be adjusted again so it will always aim for 5 minutes of idleness.
If you really want to reset the active time then you will actually need to trigger some activity either by moving the mouse or sending a keypress

windows service timer set to weekly

I have a windows service running with several timed functions:
_timer = new Timer(1 * 60 * 1000); // every 1 minute
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Start();
_fbtimer = new System.Timers.Timer(48 * 60 * 60 * 1000);
_fbtimer.Elapsed += new System.Timers.ElapsedEventHandler(fbtimer_Elapsed);
_fbtimer.Start();
//Weekley Snapshot
_ventimer = new System.Timers.Timer(2 * 60 * 1000);
_ventimer.Elapsed += new System.Timers.ElapsedEventHandler(ventimer_Elapsed);
_ventimer.Start();
//Weekly Activity
_tevtimer = new System.Timers.Timer(2 * 60 * 1000);
_tevtimer.Elapsed += new System.Timers.ElapsedEventHandler(tevtimer_Elapsed);
_tevtimer.Start();
How do i set the timer to occur say once a week, or even better set it to a specific time on one day a week, without using quatrz/windows scheduler or a too different method.
Addition: this is how i am running a task everyday at 10
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//log.Info("Info - Check time");
DateTime startAt = DateTime.Today.AddHours(10);
if (_lastRun < startAt && DateTime.Now >= startAt)
{
_timer.Stop();
//Stuff
_lastRun = DateTime.Now;
_timer.Start();
}
}
without using quatrz/windows scheduler or a too different method.
Why reinvent the wheel, poorly? Anyway a weekly timer won't do much good. What if you code the timer to wait a week, and the machine reboots halfway the week for updates? The timer will start waiting a week again.
You'd better let it run at a small interval and check each time whether it's time to run the method you want. This way you can pre-calculate the 'event time' and check for it each time.

Exactly fire tick event on completion of hour in C# Timer

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.

Execute an operation every x seconds for y minutes in c#

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

Categories

Resources