Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Inplement a precise timer

Inplement a precise timer

Scheduled Pinned Locked Moved C#
csharpdatabasequestion
23 Posts 13 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C cateyes99

    In .net we've got several timers, but all of them specify an interval to elapse rather than a specific time to come. I'd like to implement a timer which specifies a specific time, say to be triggered at the time of 10:25:15am (hour:minute:second). Using polling tech to determine if it's the right time to trigger is a very bad way and inefficient, I'd like to put the timer to sleep, then when the time is coming it receives a signal from the system to be woken up and then do its work. One way to do this is still based on the Threading.Timer, convert how long to wait for the specific time into interval. But is there any mechanism provided by .net directly supporting this scenario to signal the thread at specific time? Many thanks.

    A Offline
    A Offline
    agolddog
    wrote on last edited by
    #13

    My answer starts in the wayback machine, before things such as .net and controls and whatnot existed. It's an alternate idea, but probably doesn't do what you want. Anyway, back a long time ago, we had systems which needed to do take certain actions at certain times. We bulit a server application which would go in our data and look for certain conditions. When they were met, an event would happen. I wonder if you could write a service to do something similar. When you know you want to trigger an event at 10:25:15, you write to an event table, noting the event name and time. The service is pretty simple; look in the event table for things in the past which are in a state of 'not run'; fire off an appropriate class/method based on event name, mark as 'complete' the event entry. Mark as 'run, but with exception' if the action fails. I think this solution depends on how time-specific your answer really needs to be. If it's life-critical, this is no good. If it's within a few seconds, this might be a pretty simle solution.

    C 1 Reply Last reply
    0
    • P Pete OHanlon

      Don't use a timer for this - take a look, rather, at using something like a Monitor where you can specify an elapsed interval before the monitor "wakes up". It would look something like this:

      private static readonly object _syncLock = new object();
      private bool _cancel;
      private void ScheduleProcess(DateTime scheduledDate)
      {
      if (scheduledDate >= DateTime.Now)
      throw new ArgumentOutOfRangeException("The scheduled time is set for a time that has already passed.");
      TimeSpan waittime = scheduledDate - DateTime.Now;
      lock (_syncLock)
      {
      Monitor.Wait(_syncLock, waittime);
      }
      }

      public void Cancel()
      {
      _cancel = true;
      lock(_syncLock)
      {
      Monitor.PulseAll(_syncLock);
      }
      }

      Create a background thread, and use ScheduleProcess to block access to your functionality until the time has passed. For instance:

      public void DoSomething(DateTime scheduledTime)
      {
      SmartThreadPool stp = new SmartThreadPool();
      stp.QueueWorkItem(new WorkItemCallback(RunProcess), scheduledTime);
      }

      private object RunProcess(object scheduledTime)
      {
      ScheduleProcess((DateTime)scheduledTime);
      if (!_cancel)
      {
      // Run my process
      }

      return null;
      }

      This example uses the SmartThreadPool[^].

      I have CDO, it's OCD with the letters in the right order; just as they ruddy well should be

      Forgive your enemies - it messes with their heads

      My blog | My articles | MoXAML PowerToys | Onyx

      T Offline
      T Offline
      Tom Foswick
      wrote on last edited by
      #14

      Using Monitor.Wait() is a great solution but comes with its own set of problems. Most notably, it has no guaranteed accuracy. If you tell it to wait one hour, it will wait AT LEAST one hour. A number of factors can delay the response. It would be much safer to use Monitor.Wait() to suspend the thread, then switch to a more accurate but processor-intensive method for precision. Also, when calculating the delay, since a number of factors (already pointed out by someone else) can cause this delay to be off, if you really want precision, I would calculate it a few times, then perform the reverse calculation for each result. This will allow you to be assured that your delay value is accurate.

      C 1 Reply Last reply
      0
      • P Pete OHanlon

        Don't use a timer for this - take a look, rather, at using something like a Monitor where you can specify an elapsed interval before the monitor "wakes up". It would look something like this:

        private static readonly object _syncLock = new object();
        private bool _cancel;
        private void ScheduleProcess(DateTime scheduledDate)
        {
        if (scheduledDate >= DateTime.Now)
        throw new ArgumentOutOfRangeException("The scheduled time is set for a time that has already passed.");
        TimeSpan waittime = scheduledDate - DateTime.Now;
        lock (_syncLock)
        {
        Monitor.Wait(_syncLock, waittime);
        }
        }

        public void Cancel()
        {
        _cancel = true;
        lock(_syncLock)
        {
        Monitor.PulseAll(_syncLock);
        }
        }

        Create a background thread, and use ScheduleProcess to block access to your functionality until the time has passed. For instance:

        public void DoSomething(DateTime scheduledTime)
        {
        SmartThreadPool stp = new SmartThreadPool();
        stp.QueueWorkItem(new WorkItemCallback(RunProcess), scheduledTime);
        }

        private object RunProcess(object scheduledTime)
        {
        ScheduleProcess((DateTime)scheduledTime);
        if (!_cancel)
        {
        // Run my process
        }

        return null;
        }

        This example uses the SmartThreadPool[^].

        I have CDO, it's OCD with the letters in the right order; just as they ruddy well should be

        Forgive your enemies - it messes with their heads

        My blog | My articles | MoXAML PowerToys | Onyx

        C Offline
        C Offline
        cateyes99
        wrote on last edited by
        #15

        Thanks very much for your example.

        1 Reply Last reply
        0
        • T Tom Foswick

          Using Monitor.Wait() is a great solution but comes with its own set of problems. Most notably, it has no guaranteed accuracy. If you tell it to wait one hour, it will wait AT LEAST one hour. A number of factors can delay the response. It would be much safer to use Monitor.Wait() to suspend the thread, then switch to a more accurate but processor-intensive method for precision. Also, when calculating the delay, since a number of factors (already pointed out by someone else) can cause this delay to be off, if you really want precision, I would calculate it a few times, then perform the reverse calculation for each result. This will allow you to be assured that your delay value is accurate.

          C Offline
          C Offline
          cateyes99
          wrote on last edited by
          #16

          thanks for pointing out this.

          1 Reply Last reply
          0
          • R roman400

            May be you should look at API functions CreateWaitableTimer(), SetWaitableTimer() and CancelWaitableTimer(). SetWaitableTimer() has the ability to specify UTC-based absolute time. Dont't know, if these functions are implemented directly in BCL though. THT.

            C Offline
            C Offline
            cateyes99
            wrote on last edited by
            #17

            thanks for the info.

            1 Reply Last reply
            0
            • E englebart

              If you consider one second as precise enough, this should suffice. When I hear precision timer, I am thinking microsecond or nanosecond accuray. http://quartznet.sourceforge.net/[^]

              C Offline
              C Offline
              cateyes99
              wrote on last edited by
              #18

              Actually, I also meant 'micorsecond' :) (well, I'm not sure whether .net can really cater for nanosecond accuray or not) I'll take look at quartz.net, thanks.

              modified on Thursday, September 2, 2010 6:28 PM

              1 Reply Last reply
              0
              • A agolddog

                My answer starts in the wayback machine, before things such as .net and controls and whatnot existed. It's an alternate idea, but probably doesn't do what you want. Anyway, back a long time ago, we had systems which needed to do take certain actions at certain times. We bulit a server application which would go in our data and look for certain conditions. When they were met, an event would happen. I wonder if you could write a service to do something similar. When you know you want to trigger an event at 10:25:15, you write to an event table, noting the event name and time. The service is pretty simple; look in the event table for things in the past which are in a state of 'not run'; fire off an appropriate class/method based on event name, mark as 'complete' the event entry. Mark as 'run, but with exception' if the action fails. I think this solution depends on how time-specific your answer really needs to be. If it's life-critical, this is no good. If it's within a few seconds, this might be a pretty simle solution.

                C Offline
                C Offline
                cateyes99
                wrote on last edited by
                #19

                Definitely, we can do it in this way, but the thing is what techique I can use in .net not to rely on the inefficient polling tech (and polling is not accurate as well). I'd like to let the working thread to sleep and when the specific time coming, woken up. This model is what I really want. I wonder if .net has mechanism directly support this model, don't have to do converting interval stuff. By the way, if the time-specific matter needs to meet life-critical requirement, what .net mechanism we can rely on? Does .net have such capability to support this level of accuracy? (My understanding is this needs real-time OS and device to support).

                A 1 Reply Last reply
                0
                • C cateyes99

                  Definitely, we can do it in this way, but the thing is what techique I can use in .net not to rely on the inefficient polling tech (and polling is not accurate as well). I'd like to let the working thread to sleep and when the specific time coming, woken up. This model is what I really want. I wonder if .net has mechanism directly support this model, don't have to do converting interval stuff. By the way, if the time-specific matter needs to meet life-critical requirement, what .net mechanism we can rely on? Does .net have such capability to support this level of accuracy? (My understanding is this needs real-time OS and device to support).

                  A Offline
                  A Offline
                  agolddog
                  wrote on last edited by
                  #20

                  I think you're right on the life-critical aspect. I don't believe there is anything in .net that will give you that granularity. I don't know if my idea fits your needs, or is even a step down the right path. In the solution I was talking about, we knew every time an action was taken exactly what the next 'automatic' action would be, and exactly when it would occur. However, for us, not so time-critical. So, even though we were able to come up with a simple 'if this happens, write this event and time to the database' scenario, our server wouldn't necessarily notice that event right at the time written. But, it did turn out to be a really simple solution to a timer-type problem. I suppose in today's world, you'd just go ahead and use a Timer and tie it to the event you wanted to perform. Anyway, good luck.

                  R 1 Reply Last reply
                  0
                  • L Luc Pattyn

                    I'm not aware of any explicit support for a due time. For a 1-second resolution I would just pick some timer (Windows.Forms/Threading/Timers depending on circumstances) and use DateTime and TimeSpan classes to calculate and set the delay. For a finer resolution, I'd start with the above, then probably execute some polling loop within the final second, including a Thread.Sleep(ms) with a number of milliseconds fitting the resolution (assuming >= 50) Whatever you do, keep in mind things could go wrong in several ways: - your PC might get very busy while calculating and setting the due time, resulting in a late call; - your PC might get very busy at the due time, so the requested action may actually run somewhat later; - your PC might be switched off or crash in the mean time. Depending on your requirements a Windows scheduled task may or may not be a better option. :)

                    Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum

                    Please use <PRE> tags for code snippets, they preserve indentation, and improve readability.

                    C Offline
                    C Offline
                    cateyes99
                    wrote on last edited by
                    #21

                    Yep, Windows scheduled task may be a way. But it needs to be reused/consumed by other programs, so using Windows scheduled task is out of scope.

                    1 Reply Last reply
                    0
                    • G Garth J Lancaster

                      quartz.net has a number of timers, a cron type timer being amongst them - may be worth a look 'g'

                      C Offline
                      C Offline
                      cateyes99
                      wrote on last edited by
                      #22

                      thanks, i'll take a look at quartz.net.

                      1 Reply Last reply
                      0
                      • A agolddog

                        I think you're right on the life-critical aspect. I don't believe there is anything in .net that will give you that granularity. I don't know if my idea fits your needs, or is even a step down the right path. In the solution I was talking about, we knew every time an action was taken exactly what the next 'automatic' action would be, and exactly when it would occur. However, for us, not so time-critical. So, even though we were able to come up with a simple 'if this happens, write this event and time to the database' scenario, our server wouldn't necessarily notice that event right at the time written. But, it did turn out to be a really simple solution to a timer-type problem. I suppose in today's world, you'd just go ahead and use a Timer and tie it to the event you wanted to perform. Anyway, good luck.

                        R Offline
                        R Offline
                        rhp8090
                        wrote on last edited by
                        #23

                        FWIW: In a Windows Service that I wrote awhile back, I used the following: // Initiate our System Timer (set to one minute here) double dblStartupInterval = 60000; this.timProcessTimer_PollPV = new System.Timers.Timer (dblStartupInterval); // Note that everything done by the Timer is tied to // the Elapsed Event, which is raised every interval. // Instruct the Framework to call // the "ServiceTimer_PollPV_Tick" method when this // Timer elapses -- that is, when its interval runs its course. this.timProcessTimer_PollPV.Elapsed += new System.Timers.ElapsedEventHandler(this.ServiceTimer_PollPV_Tick);

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups