Solved Multiple events at different times from one timer. (1 Viewer)

Local time
Today, 05:50
Joined
Feb 28, 2023
Messages
628
This is related to this question: https://www.access-programmers.co.u...-disable-right-click-close-menu.328536/page-2

I've seen the answer before, but I don't remember what it was and I couldn't find it in a search.

I want to run one event (re-open the switchboard if closed) every 5 seconds, and another event (check for logout file), every 60 seconds from one hidden form.

I don't know if I can have multiple timers on the same form ...

I think the form code would look something like this:

Code:
Me.TimerInterval = 1000 ' Run timer every second
If CLong(Timer/5) = Timer/5 Then 'Every 5 seconds
    ' Reset Switchboard
End If
If CLong(Timer/60) = Timer/60 Then 'Every 60 seconds
    ' Check for logout file
End If

It's this line I'm not sure about:
If CLong(Timer/5) = Timer/5 Then

I don't recall if it was CLong, CInt, Rnd, Remainder of Timer/5 = 0 etc.

Thanks in advance!!!
 

Josef P.

Well-known member
Local time
Today, 11:50
Joined
Feb 2, 2023
Messages
826
If CLong(Timer/5) = Timer/5 Then 'Every 5 seconds
Then you have to catch the exact right moment. Have you looked at the output of Timer yet?
Note that the TimerEvent of a form does not trigger at a specific time, but only after the TimerInterval has expired and the scope is available.

2 variants:
Code:
Private Sub Form_Timer()

   Static NextRun(1) As Long

   Dim CheckTimer As Long
   CheckTimer = CLng(Timer)

   If CheckTimer > NextRun(0) Then
      Debug.Print "Proc 0", Timer, Now()
      NextRun(0) = CheckTimer + 5
   End If

   If CheckTimer > NextRun(1) Then
      Debug.Print "Proc 1", Timer, Now()
      NextRun(1) = CheckTimer + 60
   End If

End Sub

Code:
Private Sub Form_Timer()
' Assumption: timer runs every 1 second .. for whatever reason, I'd only run it every 5 seconds if that's the smallest pürfin interval.
  const Proc0Counter as long = 5
  const Proc1Counter as long = 60 ' = 12 * 5

   Static TimerCounter As Long

   TimerCounter = TimerCounter + 1 ' or at the end of proc if all should run on first call (TimerCounter == 0)

   If TimerCounter Mod Proc0Counter = 0 Then
      Debug.Print "Proc 0", Timer, Now()
   End If

   If TimerCounter Mod Proc1Counter = 0 Then
      Debug.Print "Proc 1", Timer, Now()
   End If

End Sub
 
Last edited:
Local time
Today, 05:50
Joined
Feb 28, 2023
Messages
628
Thank you!!! - I went with the second variant - works a charm!!!
 

Josef P.

Well-known member
Local time
Today, 11:50
Joined
Feb 2, 2023
Messages
826
Only as an addition:
It is also possible to run multiple timers, e.g. with one subform per required timer or using API timers.
 
Local time
Today, 05:50
Joined
Feb 28, 2023
Messages
628
Thank you - I didn't think of subforms or API Timers. I did think of adding an additional hidden form with the 5-second timer, but didn't want two hidden forms loading at startup!!!
 

Josef P.

Well-known member
Local time
Today, 11:50
Joined
Feb 2, 2023
Messages
826
Attached is an example with subforms for multiple timers.
This variant can be clearer if several timer intervals are needed.

/edit: it would also work without subforms with an instanced form.

With subforms (see attachment):
Code:
Private Sub InitTimer()

   Set m_TimerEventForm_1 = Me.sfrTimerForm1.Form
   Set m_TimerEventForm_2 = Me.sfrTimerForm2.Form
   Set m_TimerEventForm_3 = Me.sfrTimerForm3.Form
 
   m_TimerEventForm_1.TimerInterval = 1000
   m_TimerEventForm_2.TimerInterval = 3000
   m_TimerEventForm_3.TimerInterval = 10000

End Sub

without subforms:
Code:
Private Sub InitTimer()

   Set m_TimerEventForm_1 = New Form_frmTimerEventTrigger
   Set m_TimerEventForm_2 = New Form_frmTimerEventTrigger
   Set m_TimerEventForm_3 = New Form_frmTimerEventTrigger
 
   m_TimerEventForm_1.TimerInterval = 1000
   m_TimerEventForm_2.TimerInterval = 3000
   m_TimerEventForm_3.TimerInterval = 10000

End Sub
 

Attachments

  • TimerWith_Subforms.zip
    22.5 KB · Views: 72
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 04:50
Joined
Feb 28, 2001
Messages
27,186
Typically, but not always, your operating system gets in the way of having multiple simple timers by giving you only one event callback point in its "easy" timer. What I mean by "easy" timer is that you get an ALMOST free timer where all you need is the callback entry point and the amount of time to be placed in the timer countdown slot. So now, specific to the Access environment, a form has a single timer countdown value and a single callback point. Which means that when using the "easy" timer you have to code up multiple actions as described by Josef P.

It is possible to set up independent timers where you start a timer through the O/S (in Windows, an API timer) and give that individual timer its own unique callback entry. But if you are going to stick with the "easy" timer then the countdown value (the timer interval) has to be the fastest of the multiple events you are going to stack together into a single event routine.

But there is a catch... you also need to assure that your slower intervals are integral multiples of the fastest interval. For example, if you have an interval of 200 msec and another one of 500 msec, the slower interval is NOT an integer multiple of the faster interval. Then you have to either live with the mismatch knowing that the slower interval will be off a bit sometimes, or you must pick an interval that is the lowest common denominator (LCD) of both intervals... in this case, 100 msec for the ACTUAL interval. If you have two event actions, the LCD isn't that hard. Now add a third action, because now you have to pick the LCD of a three-way comparison.

I first ran into this concept in my college days when I was doing sampling of an analog channel hooked up to a photomultiplier tube and I had to also display certain things while the data-gathering experiment was running. My interval was 200 microseconds because this was a real-time data gathering experiment measuring chemical reaction speed optically. The trick here is to decide what you actually need to do in the timer and what you need to do in non-timer code after the process is complete. It was true in 1970's machine language interrupt code where equal-priority interrupts could not interrupt each other, and it is true in 2020's Access, where one event routine cannot interrupt another.
 

Users who are viewing this thread

Top Bottom