Solved

run function at a interval duration

Posted on 2001-06-15
12
285 Views
Last Modified: 2010-05-02
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
Comment
Question by:chrislee8
  • 5
  • 3
  • 3
  • +1
12 Comments
 
LVL 18

Accepted Solution

by:
bobbit31 earned 50 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

Private Sub form_load()

    boolRunning = False

End Sub

Private Sub timer1_timer()

    Static numMinutes As Integer
   
    If numMinutes = 5 And boolRunning = False Then
        boolRunning = True
       
        '' run your functions
       
        numMinutes = 0
        boolRunning = False
    Else
        numMinutes = numMinutes + 1
    End If
       

End Sub
0
 
LVL 2

Expert Comment

by:TravisHall
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

by:dmarco
ID: 6199063
Hi,

You can also use the system timer :

Dim start as Single

Private Sub Form_Load()

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

by:dmarco
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


Private Sub Form_Load()

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

by:chrislee8
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.

TravisHall, please post some codes, i love to learn more in different situation.

Thanks again.
0
 

Author Comment

by:chrislee8
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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:chrislee8
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

by:TravisHall
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
d = DateAdd("n", 1, 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
        d = DateAdd("n", 1, 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...
Dim lThreadID As Long
mhClockThread = CreateThread(0, 0, AddressOf mdlTimers.ClockLoop, mhClockTimer, 0, lThreadID)
0
 
LVL 2

Expert Comment

by:TravisHall
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

by:dmarco
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

by:chrislee8
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

by:chrislee8
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

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
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…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now