Dot NET
Dot NET

Reputation: 4907

How to make timer fire in a recurring manner

I have a timer which I want to expire every Monday at 5pm. When testing the application, as soon as it reaches 5pm on a Monday, my task is fired as it is supposed to.

However, when I change the system date and time to the following week at 5pm, the task does not fire. This is my code:

Timer timer = new Timer(callback, application, timeToEnd, TimeSpan.FromDays(7));

I have a feeling that it has something to do with the TimeSpan.FromDays(7) part. Any ideas?

Upvotes: 2

Views: 777

Answers (5)

Jim Mischel
Jim Mischel

Reputation: 134125

If you want a timer that will fire at a specific time, use a Waitable Timer. Unfortunately, the .NET libraries don't have a wrapper for that timer. I wrote one some time back for an article. The article is no longer available online, but you can download the source code from http://mischel.com/pubs/waitabletimer.zip.

That said, it sounds to me what you have is a catnap program. Do as others have suggested and make it a simple console app that you control with Scheduled Tasks.

Upvotes: 1

Sriram Sakthivel
Sriram Sakthivel

Reputation: 73502

You're now in trouble. We asked the framework to notify you after x days, y hours, z minutes. So timer will fire exactly after what time you told it to.

I know this is not the right way to go, but this will work.

SystemEvents.TimeChanged += SystemEvents_TimeChanged;

static void SystemEvents_TimeChanged(object sender, EventArgs e)
{
    timer.Dispose();//Dispose your previous timer
    SetTimerAgain();//Call the method which sets the timer again. you're done
}

I recommend "Windows Scheduled Tasks", but for some reason you can't so here is the way to go.

Also you could run a periodic timer as @giammin suggested.

TimerCallback callback = (state) =>
{      
    var now = DateTime.Now; 
    if(now.DayOfWeek == DayOfWeek.Monday 
     && now.TimeOfDay.Hours == 17 && now.TimeOfDay.Minutes == 0)
    {
        MyMethod();
    }
};

Timer timer = new Timer(callback, application, 0, 10000);//10seconds

With the latter approach you should defend yourself from calling the method again and again for the same day.

Upvotes: 1

D Stanley
D Stanley

Reputation: 152644

This is not a good use for a Timer. You should create a console application that does what you want, then schedule it with Windows Scheduler or a 3rd party scheduling tool.

Otherwise, the safer thing to do is to set the timer to run at a short interval (1 minute?) and check the system clock to see if it needs to run or not (e.g. is it within 1 minute of 5:00?)

Upvotes: 2

Martin Liversage
Martin Liversage

Reputation: 106936

If you do not want to rely on an external service like the Window Task Scheduler you will have to create a timer that fires at regular intervals (say every minute) and checks the current time, and if the current time has passed the next expiration time it actually performs the desired action (including setting up the next expiration time).

Performing a time check every minute should not be a problem unless you are running on a low powered device.

Moving the clock forward a week is a pretty extreme measure but daylight savings can also move the clock and in particular on virtual machines you may have some unexpected clock drift. This is why checking the current time at regular intervals most of the time is better than just setting a timer to fire at some distant future time.

Speaking of daylight savings you need to handle the situation where the clock moves backward one hour in case your want to perform you activity in that interval.

Upvotes: 1

giammin
giammin

Reputation: 18968

None of the timers depend on the system time.

Changing the clock will not affect System.Windows.Forms.Timer, System.Timers.Timer, or System.Threading.Timer.

If you need to handle those situation you have to rely on SystemEvents.TimeChanged

Otherwise you can check periodically for DateTime.Now.DayOfWeek == DayOfWeek .Monday

Upvotes: 1

Related Questions