Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
Solved

# run function at a interval duration

Posted on 2001-06-15
Medium Priority
293 Views
I have an VB app.
the App run a general function "GenFunction"

"GenFunction" call other functions to complete tasks.

say like the GenFunction take about 3-5 minutes to finish.

now, I want to run the GenFunction every 5 minutes exact.

2 questions:
1. how to run the GenFunction every 5 minutes.

2. what if the previous Genfunction call longer than 5 minutes and the next call is about to start? how to avoid this?

I can't make the interval duration longer, 'cause I don't know how long the previous call will actually take.

I want to have the flexibility to run the second call after the previous one is done.

simplify it:

if 1st call is < 5 min, run 2nd in 5 min.
if 1st call is > 5 min, run 2nd after the 1st is done.

am I asking too much, or it is just very simple to do?

Thanks
0
Question by:chrislee8
[X]
###### Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 5
• 3
• 3
• +1

LVL 18

Accepted Solution

bobbit31 earned 150 total points
ID: 6196697
put a timer on your form and set the interval to 60000 (1 minute) (the max interval is around 60k milliseconds)

then do something like this:

Dim boolRunning As Boolean

boolRunning = False

End Sub

Private Sub timer1_timer()

Static numMinutes As Integer

If numMinutes = 5 And boolRunning = False Then
boolRunning = True

numMinutes = 0
boolRunning = False
Else
numMinutes = numMinutes + 1
End If

End Sub
0

LVL 2

Expert Comment

ID: 6197315
bobbit31's answer is good. There more elegant techniques for getting something to occur at intervals greater than five minutes, but then often elegance does and should take second place to just getting the thing working. I can probably find you a bit of relevant code for that on Monday, if you want it.

A sometimes-useful variation, though, is to have GenFunction set its next execution time as the last thing it does. Again, say if you want to see some code, because I think I've got a little at work.
0

LVL 2

Expert Comment

ID: 6199063
Hi,

You can also use the system timer :

Dim start as Single

again:
start = Timer

Call GenFunction

Do While Timer <= start + 300   '= 5 minutes'
DoEvents
Loop
GoTo again

End Sub

cheers Marco
0

LVL 2

Expert Comment

ID: 6199897
Sorry, there is a bug in my code: the Timer function is reset to zero at midnight, therefore the routine I wrote get an endless loop, if you run it less than 5 minutes before midnight (it's Dracula's time ..:-))

To avoid this problem :

Dim start As Single
Private Const MIDN = 86399
Dim startM As Single

again:
start = Timer + 300 'set 5 minutes timing'
If start >= MIDN Then startM = start - MIDN: start = MIDN

Call GenFunction

Midnight:
Do While Timer <= start
DoEvents
Loop

If Timer >= MIDN Or Timer < 2 Then
start = startM
GoTo Midnight
End If

GoTo again
End Sub

Of course you can put this code in a subroutine and not in the form_load event or use a flag setting and not a direct call of your function...

0

Author Comment

ID: 6202528
hi, everyone, thanks for the inputs.

I will be working on it today to find the right way, I am still open for any suggestion.

I will be testing the codes to see which one fits my position the best.

Thanks again.
0

Author Comment

ID: 6202668
hi, marco and bobbit

does the timer get reset to 0 at midnight by design, or it is only for the function wrote by marco?

bobbit, your sample directs me to the right way, after little mods, I am able to have my app working. Thank you

I am running a test tonight, if it works through midnight, I should grant you the points.

hehe :)
0

Author Comment

ID: 6202711
oh, no

I miss a point. :(

how can I put the timer only work with a function instead of form_load or main()?

I want the timer starts ticking after I hit a button or I call a function.

sorry, any suggestion to that?
0

LVL 2

Expert Comment

ID: 6204325
Well, the most relevant chunk of code I could think of is the code I use to run a clock in an app - time changing once a second, pretty much on the second. Why not just use a timer control? Because I needed to develop the technique so I could code some things that the timer wouldn't quite do right.

BTW, this code creates its own thread. The VB design environment hates that, and generally crashes if you try it in debug mode, but the code works in a compiled version. I don't let this code run in debug mode.

Public Declare Function CreateWaitableTimer Lib "kernel32" Alias "CreateWaitableTimerA" (ByVal lpSemaphoreAttributes As Long, ByVal bManualReset As Long, ByVal lpName As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function SetWaitableTimer Lib "kernel32" (ByVal hTimer As Long, lpDueTime As FILETIME, ByVal lPeriod As Long, ByVal pfnCompletionRoutine As Long, ByVal lpArgToCompletionRoutine As Long, ByVal fResume As Long) As Long
Private Declare Function MsgWaitForMultipleObjects Lib "user32" (ByVal nCount As Long, pHandles As Long, ByVal fWaitAll As Long, ByVal dwMilliseconds As Long, ByVal dwWakeMask As Long) As Long
Private Const WAIT_ABANDONED_0& = &H80&
Private Const WAIT_OBJECT_0& = 0
Private Const WAIT_TIMEOUT& = &H102&
Private Const QS_HOTKEY& = &H80
Private Const QS_KEY& = &H1
Private Const QS_MOUSEBUTTON& = &H4
Private Const QS_MOUSEMOVE& = &H2
Private Const QS_PAINT& = &H20
Private Const QS_POSTMESSAGE& = &H8
Private Const QS_SENDMESSAGE& = &H40
Private Const QS_TIMER& = &H10
Private Const QS_MOUSE& = (QS_MOUSEMOVE _
Or QS_MOUSEBUTTON)
Private Const QS_INPUT& = (QS_MOUSE _
Or QS_KEY)
Private Const QS_ALLEVENTS& = (QS_INPUT _
Or QS_POSTMESSAGE _
Or QS_TIMER _
Or QS_PAINT _
Or QS_HOTKEY)
Private Const QS_ALLINPUT& = (QS_SENDMESSAGE _
Or QS_PAINT _
Or QS_TIMER _
Or QS_POSTMESSAGE _
Or QS_MOUSEBUTTON _
Or QS_MOUSEMOVE _
Or QS_HOTKEY _
Or QS_KEY)

Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type

Private Declare Function SystemTimeToFileTime Lib "kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As Long
Private Declare Function LocalFileTimeToFileTime Lib "kernel32" (lpLocalFileTime As FILETIME, lpFileTime As FILETIME) As Long
Private Declare Function FileTimeToSystemTime Lib "kernel32" (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long
Private Declare Function FileTimeToLocalFileTime Lib "kernel32" (lpFileTime As FILETIME, lpLocalFileTime As FILETIME) As Long
Private Const INFINITE = &HFFFF

Public Sub ClockLoop(ByRef hTimer As Long)
Dim lRet As Long
Dim st As SYSTEMTIME
Dim ft As FILETIME
Dim d As Date

d = Now
frmEditor.SetClock d
DateToSystemTime d, st
st.wSecond = 0
SystemTimeToFileTime st, ft
LocalFileTimeToFileTime ft, ft

SetWaitableTimer hTimer, ft, 0, 0, 0, 0

Do
lRet = MsgWaitForMultipleObjects(1, hTimer, 0, INFINITE, QS_ALLEVENTS Or QS_ALLINPUT)
Select Case lRet
Case WAIT_OBJECT_0
UTCFileTimeToDate ft, d
frmEditor.SetClock d
DateToUTCFileTime d, ft
SetWaitableTimer hTimer, ft, 0, 0, 0, 0
Case WAIT_OBJECT_0 + 1
DoEvents
End Select
Loop
End Sub

Private Sub DateToSystemTime(d As Date, st As SYSTEMTIME)
st.wDay = Day(d)
st.wDayOfWeek = WeekDay(d)
st.wHour = Hour(d)
st.wMilliseconds = 0
st.wMinute = Minute(d)
st.wMonth = Month(d)
st.wSecond = Second(d)
st.wYear = Year(d)
End Sub

Private Sub DateToUTCFileTime(d As Date, ft As FILETIME)
Dim st As SYSTEMTIME

st.wDay = Day(d)
st.wHour = Hour(d)
st.wMilliseconds = 0
st.wMinute = Minute(d)
st.wMonth = Month(d)
st.wSecond = Second(d)
st.wYear = Year(d)
SystemTimeToFileTime st, ft
LocalFileTimeToFileTime ft, ft
End Sub

Private Sub UTCFileTimeToDate(ft As FILETIME, d As Date)
Dim st As SYSTEMTIME
FileTimeToLocalFileTime ft, ft
FileTimeToSystemTime ft, st
d = DateSerial(st.wYear, st.wMonth, st.wDay) + TimeSerial(st.wHour, st.wMinute, st.wSecond)
End Sub

And kick it off with...
0

LVL 2

Expert Comment

ID: 6204344
As for getting your timer to work only after hitting a button or calling a function, just use the Enabled property of the control. Set it to False at design-time, and use code like:

Private Sub cmdStart_Click()
Timer1.Enabled = True
End Sub

(And them's Bobbit's points, don't try to award me points just for pointing out the Enabled property.)
0

LVL 2

Expert Comment

ID: 6204405
Hi chrislee8,

the reset to 0 is only for the Timer function I used in my code. The Timer control used by bobbit doesn't suffer of the dracula's syndrome.:-)) The limitation of this control is the max timing interval of one timing cycle = 64.000 msec = approx 1 minute.

However I tested successfully the second code I posted for you and it worked fine also trhought midnight. (You can adjust your computer date and time close to midnight and  then test your app).

<<I want the timer starts ticking after I hit a button or I call a function>>

Add a command button (Command1) to your form and put the code in a click event routine:

Private Sub Command1_Click()

again:
start = Timer + 300 'set 5 minutes timing'
If start >= MIDN Then startM = start - MIDN: start = MIDN

Call GenFunction

Midnight:
Do While Timer <= start
DoEvents
Loop

If Timer >= MIDN Or Timer < 2 Then
start = startM
GoTo Midnight
End If

GoTo again

End Sub

When you click the command button your GenFunction and the 5 minutes timing will start.
You can also put the code in a subroutine and call it from everywhere.( Don't forget to declare the constant and variables showed at the beginning of the code)

If you use the Timer control as suggested by bobbit, set the Timer enabled property to false ( Timer is not running) and add a command button :

Private Sub Command1_Click()

Timer1.Enabled = True ' Timer and your function start'

End sub

0

Author Comment

ID: 6207892
shouldn't it be numMinutes = 4 instead of 5?

because it is counted as 1 once the timer_timer event is triggered.

0

Author Comment

ID: 6207909
travis, marco

Thanks for your inputs, your codes are definitely valuable in the future for me. I am sure to study them and make them alive...

:)
have a good day!
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library aâ€¦
Most everyone who has done any programming in VB6 knows that you can do something in code like Debug.Print MyVar and that when the program runs from the IDE, the value of MyVar will be displayed in the Immediate Window. Less well known is Debug.Asseâ€¦
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can launâ€¦
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that aâ€¦
###### Suggested Courses
Course of the Month6 days, 23 hours left to enroll