Least resource hogging way to have a program 'sleep' until specified times

Posted on 2006-05-03
Last Modified: 2008-01-09
I normally use 'doevents' in a loop to have a program wait for a specified trigger but judging by the program's CPU usage while it's waiting, this isn't the best way to go.

I need to have a program trigger and record text on a webpage every 1/2 hour. I've thought about using Windows Scheduled TAsks to do this, but the lowest time denomination you can repeatedly run a program is once daily.

It'd be nice to have the program open and left that way while it waits every 1/2 hour to record text on the webpage without using as many CPUs as 'doevents' does. Any suggestions?
Question by:JohnDoeSr
    LVL 85

    Accepted Solution

    Add a Timer control to a Form (the Form Visible propery can be false if you don't want to see it):

    ' --------------------
    '  Form1
    ' --------------------
    Option Explicit

    Private targetTime As Date

    Private Sub Form_Load()
        ScheduleNextEvent 30
    End Sub

    Private Sub ScheduleNextEvent(ByVal delayInMinutes As Integer)
        targetTime = DateAdd("n", delayInMinutes, Now()) ' in XXX minutes from now...
        Timer1.Interval = 1000 ' check every second (change to suit your needs)
        Timer1.Enabled = True
    End Sub

    Private Sub Timer1_Timer()
        If Now() > targetTime Then
            Timer1.Enabled = False
            ' place your code to be executed here
            ' or make a call to another sub
            ScheduleNextEvent 30
        End If
    End Sub
    LVL 10

    Assisted Solution

    Hi here's a skeleton extracted from a working NT service process I wrote for a shop floor data monitor. I've modded it slightly as I'm working on shorter intervals, and a process cycle of the order of 300 to 400 ms.
    I've commented out the first def of const MajorInterval (30 mins) and replaced it with a shorter one (2 mins) for testing. just create a new project with an interval timer on the form named 'Timer', paste this code into the editor, and run it. watch the immediate window.

    Regards .. Alan

    Option Explicit
    'Const defMajorInterval As Long = 1800000 ' 30 mins in ms
    Const defMajorInterval As Long = 120000 ' 2 mins in ms
    Const defMinorInterval As Long = 60000 ' Timer tick in ms (Max is 65535)
    Const DaySecs          As Long = 86400      ' Number of seconds in a day
    Dim ProcTime           As Long              ' The time for a single passthrough Timer process
    Dim MajorInterval      As Long ' Time to next major interval in ms
    Dim MinorInterval      As Long ' Time to next minor interval in ms

    Private Sub Form_Load()
        MajorInterval = 0
        Timer_Timer ' Call Timer tick process explicitly with MajorInterval = 0
                    ' This will carry out the first process, and set the timer for re-iteration
    End Sub

    Private Sub Timer_Timer()
        Timer.Enabled = False ' Don't want another timer tick whilst processing
        If MajorInterval = 0 Then ' Process first through, then after every MajorInterval
            ProcTime = CLng(Timer() * 1000)
            ' ********************
            '  This is where you carry out your processing
            Debug.Print Now()
            ' ********************
            ProcTime = (CLng(Timer() * 1000) - ProcTime)
            If ProcTime < 0 Then
                ProcTime = ProcTime + DaySecs ' Turned Midnight
            End If
        End If
        If MajorInterval = 0 Then ' MajorInterval expired, (or not started) so set Major tick
            MajorInterval = defMajorInterval
        End If
    '    MajorInterval = MajorInterval
        If MajorInterval > defMinorInterval Then ' MajorInterval not expired,
                                                 ' so set another full minor tick
            MinorInterval = defMinorInterval
            MajorInterval = MajorInterval - defMinorInterval
        Else ' remainder of MajorInteval less than default tick
            MinorInterval = MajorInterval
            MajorInterval = 0
        End If
        ' The following subtracts the processing time of this cycle from the next interval, so that
        ' overall intervals are more exact.
        ' Could run into problems if proctime regularly > defMinorInterval
        Timer.Interval = IIf(ProcTime > MinorInterval, 1, MinorInterval - ProcTime)
        Timer.Enabled = True
    End Sub

    Author Comment

    Awesome. Both answers are very informative. Will split the points.

    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

    When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
    This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
    Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
    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…

    734 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

    18 Experts available now in Live!

    Get 1:1 Help Now