Timing Challenge - (every hour on the hour)

  1. 4 months ago

    Tom D

    Apr 19 Pre-Release Testers, Xojo Pro

    I'm looking for some suggestions on an approach to achieve the result that an event will be enabled to fire every hour on the hour. The existing application has a timer that fires every 10 seconds to run a thread that checks and updates a number of processes so long as the thread is not currently running. What I would like to do is set a Boolean variable that will initiate one of the thread's run tasks to fire only when the value is true. What I'm struggling with is how to insure the the value gets set as true every hour on the hour regardless of what time of day the application was started or last paused.

    Thoughts? Suggestions?

  2. Dave S

    Apr 19 Answer San Diego, California USA

    timers are not accurate (as they can be slowed down by other system processes)
    What I have do in the past is to set a single timer and vary its period.
    each time it fired I check the actual clock... and depending on how far from the hour it was, I would shorten the period

    • Check every 55 minutes
    • adjust the period to 1/2 the remaining time
    • check the real clock
    • if clock >= hour then fire event.... goto step 1
    • goto step 2

    technincaly this should not miss the mark by more that 1 second.... but 100% accuracy is near impossible

  3. Julian S

    Apr 19 Pre-Release Testers, Xojo Pro UK

    Implementation depends on how close to the hour you want it. If you want it bang on the hour to the ms then you will need to calculate it (or use a 1ms timer), if you dont mind it being off by up to a second just use a second timer (<=1000) and check if its past 00:00 then set a bool so it knows that its fired that hour.

  4. Tom D

    Apr 19 Pre-Release Testers, Xojo Pro

    Thanks Dave. That's a decent approach. I'm not looking for absolute accuracy. I really want the task to execute predictably so that if users provide input by a certain time then they know it will get queued up for processing by a certain time. What you suggest should work.

    If anyone else has an alternate approach I might consider fire away

  5. Tom D

    Apr 19 Pre-Release Testers, Xojo Pro

    So based on Dave'd and Julian's suggestions/comments, here is what I will be trying. If you have criticism for something I've missed or suggestions to improve it I'm open to your feedback.

    Function that calculates the total second of the next hour on the hour

    Public Function GetNextHourTotalSeconds() as Double
      dim d As Date = New Date
      d.Hour = d.Hour + 1
      d.Minute = 0
      d.Second = 0
      Return d.TotalSeconds
    End Function

    Function that calculates the period to set the timer for the next hour on the hour action Event to Trigger

    Public Function GetNextBatchPeriodMilliseconds() as Integer
      Dim d As Date = New Date
      Dim nextmilliseconds As Integer
      nextmilliseconds = (GetNextHourTotalSeconds - d.TotalSeconds) * 1000
      Return nextmilliseconds
    End Function

    In the App.Open Even I call a Method called ProcessingStart() Among other things it creates two new timer objects, BatchPeriodTask and PollPeriodTask. BatchPeriodTask sets the Boolean variable BatchRun to True every hour so long as it is already False. PollPeriodTask executes a thread every 10 seconds so long as it is not already running

    Public Sub ProcessingStart()
      BatchPeriodTask = New BatchPeriodTimer
      BatchNextHourTotalSeconds = GetNextHourTotalSeconds
      BatchPeriodTask.Period = GetNextBatchPeriodMilliseconds
      BatchPeriodTask.Mode = 2
      
      PollPeriodTask = New PollPeriodTimer
      PollPeriodTask.Period = DBPollingFrequency
      PollPeriodTask.Mode = 2
      AppPaused = False
      LogTransactions("Started processing queued jobs")
    End Sub

    Timer BatchPeriodTask Action Event sets the Boolean variable BatchRun to True every hour so long as it is already False. If the timer fires before the the current total seconds is greater than or equal to the variable BatchNextHourTotalSeconds then it sets the period to wait 10 more seconds

    Sub Action() Handles Action
      Dim d As Date = New Date
      If d.TotalSeconds >= BatchNextHourTotalSeconds
        If BatchRun = False
          BatchRun = True
        End If
        BatchNextHourTotalSeconds = GetNextHourTotalSeconds
        Me.Period =  GetNextBatchPeriodMilliseconds
      Else
        Me.Period =  10000
      End If
    End Sub

    Finally in the Thread that runs every 10 seconds which the Run Event checks for a number of status changes in a database and also checks various Boolean variables, and processes changes when they have occurred, I look for the value of the variable BatchRun to be True and if so do some Batch stuff.

    Sub Run() Handles Run
      Dim b As Boolean
      Dim sqlString,desc,err As String
      MyAppThreadTaskRunning = True
      b = DBConnect(MySQLDBName)
      If b = True Then
        //----------------------------------------------------------------------------------------
        // Do some stuff
        //----------------------------------------------------------------------------------------
        If BatchRun = True
          // Do the batch Processing stuff
          BatchRun = False
        End If
        //----------------------------------------------------------------------------------------
        DBClose
      Else
        desc = "MyAppThreadTThread.DBConnect.Error"
        err = ": " + "The MyAppThread Returned a DB connection Error"
        // Log the Exception
        LogExceptions(desc+err)
        // Send a Notification Email
        SendEmail(desc + err + " - Processing Jobs was aborted." ,"MyAppThread." + desc,"text")
      End If 
      MyAppThreadTaskRunning = False
    End Sub

    Thanks for the help guys.

or Sign Up to reply!