5

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.

Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
IsmailS
  • 10,797
  • 21
  • 82
  • 134

5 Answers5

10

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.

VVS
  • 19,405
  • 5
  • 46
  • 65
  • 3
    @SubniC: I assume that he didn't know the alternative I showed him. An answer that directly answers the question is not in every case the best answer. – VVS Nov 26 '10 at 12:52
  • Can you please tell us how can one configure it to run an exe or bat file every hour on exact hour through a command line or programmatically? Can you even please tell us how to do that manually in Windows 7. And (Ironically) someone please look at the up votes. – IsmailS Nov 26 '10 at 12:56
  • @Ismail: there's lots and lots of tutorials out there on how to create tasks. – VVS Nov 26 '10 at 12:58
  • I don't know about the Win Xp which is mentioned on the link given in your answer. But I've tried exploring this option in Windows 7 which I work on and couldn't achieve what I needed. Please try yourself and let me know if you are able to do it. – IsmailS Nov 26 '10 at 13:00
  • @Ismail: That link was just a quick example of using the task scheduler in Windows XP. I removed it and added the MSDN reference instead. – VVS Nov 26 '10 at 13:02
  • Is there any programmatic way of achieving this by scheduled task? Or at least commandline? – IsmailS Nov 26 '10 at 13:15
  • @Ismail: Yes, "schtasks". I urge you to take a look at one of the samles in the MSDN documentation. – VVS Nov 26 '10 at 13:17
  • Hourly at the completion of exact hour? and how would I get a start time value on end user machine to pass to the command line? – IsmailS Nov 26 '10 at 13:18
  • @Ismail: I added a sample to my answer. Hope that helps you. – VVS Nov 26 '10 at 13:29
  • Thanks @VVS. Even I had looked at it but I had a doubt and still have that doubt. What will happen if I logged in at 8:35 am at any day? If it properly executes on 9 am and every hour thereafter, then I would like to know command for creating this schedule task. – IsmailS Nov 26 '10 at 13:45
  • @Ismail: In the Task options on the last tab is an option that lets you define if you want to rerun a missed task as fast as possible or not. In your case you don't and so the task will run the next full hour. You can also right click the created task and export it to an XML file. You can use that XML file to create the task via an installer by using the following command line: "schtasks /create /XML mytask.xml". Remember to correct the path inside the XML file. – VVS Nov 26 '10 at 14:01
  • Last but not least there is a .NET wrapper that lets you create a task from C#: http://taskscheduler.codeplex.com/ – VVS Nov 26 '10 at 14:02
  • @VVS, your choice (if works fine) is not a good option for commercial software, because end user can change his Schedule tasks, and all thing will be going to have problem. if it's an important problem, is not good to do this. – Saeed Amiri Nov 27 '10 at 15:31
  • Thanks @Saeed for pointing out. But it's all fine in my case. I don't have any such problem. @VVS! I'll surely look in to what you suggested regarding XML thing. Next thing I need to find out is, will this xml based command work on XP? I will find that out. – IsmailS Nov 29 '10 at 07:28
  • @Saeed: Trying to prevent a customer from changing sth. can fail on many levels. If you run a program from the autostart folder, registy or whatever, a customer could simply delete that entry. – VVS Jan 18 '11 at 08:31
5

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;

Saeed Amiri
  • 22,252
  • 5
  • 45
  • 83
1

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

SubniC
  • 9,807
  • 4
  • 26
  • 33
1

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 }
    }
Lee
  • 31
  • 1
  • 3
  • 1
    Welcome to stackoverflow and thanks for the answer :) . Just to let you know again, title of the question says "`EXACTLY` fire tick event on completion of hour in C# Timer." – IsmailS Jul 26 '11 at 10:46
0

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.

Mike Caron
  • 14,351
  • 4
  • 49
  • 77
  • Even checking whether the hour has changed every 20 seconds or something should be fine, you're not exactly going to be stressing the processor with that... – Alistair Evans Nov 26 '10 at 11:58
  • You gave me a good clue. May be I need to tick every second until I reach the exact hour and then immediately change the interval to 1 hour. What say? – IsmailS Nov 26 '10 at 11:59
  • @Kazar depends on the rpecision he the OP needs :) – SubniC Nov 26 '10 at 12:00
  • @Ismail that is what i suggest. – SubniC Nov 26 '10 at 12:00
  • There are reasons to keep the interval as long as possible, for as long as possible :) Maybe once a minute until you get to :59, and then once a second until :00, and then once an hour? Bah, this is getting complicated :P – Mike Caron Nov 26 '10 at 12:01
  • Why not just calculate time until first hour crossing, set a timer for that interval, then repeat the calculation? – spender Nov 26 '10 at 12:09
  • Did someone go around and mass downvote with no comments? Tsk. – Mike Caron Nov 26 '10 at 12:32
  • Hi @ Mike Caron, yes, someone did... by the way, is not complicated, how many operation can do a 1GHz processor in 1 sec? you think checking every minute is too much? – SubniC Nov 26 '10 at 12:36
  • I agree with both @Mike And @SubniC. Both is Ok for me. – IsmailS Nov 26 '10 at 13:06
  • another beauty of development :) you can do almost everything in many different ways. – SubniC Nov 26 '10 at 13:13
  • @SubniC: It's not just about cpu usage. If you're polling once every second, the operating system can never page out the memory with your code in it, since it's always running. In this case, it's not a big deal, but in general, you should avoid polling as much as possible. – Mike Caron Nov 26 '10 at 15:03
  • You are completly right @Mike Caron :) here i'm learning something new every day, Thanks :) – SubniC Nov 26 '10 at 15:30