Skip to content

cDelay Delay Object Development Documentation

vb
'===========================================================================
' Name: cDelay
' Description: Delay object class - supports event-triggered, callback,
'              and synchronous wait modes
' Author: Deng Wei, QQ: 215879458
' Website: https://vb6.pro
' Date: 2026-03-31
' Reference: cTimer.cls architecture
'===========================================================================

Overview

cDelay is a VB6 delay object class providing three usage modes:

  • Event Mode: Triggered via OnTime event
  • Callback Mode: Calls specified function via CallByName
  • Sync Mode: Blocks and waits without freezing UI

File Structure

Delay/
├── cDelay.cls      ' Delay object class
├── mDelay.bas      ' Management module (global collection, timer callback)
└── cDelayDemo.frm  ' Demo form

Features

  • ✅ Automatic lifecycle management (reference counting)
  • ✅ Support up to 9 callback parameters (using ParamArray)
  • ✅ Sync mode supports cancellation
  • ✅ Message pump implementation without DoEvents dependency
  • ✅ Thread-safe message loop

Quick Start

1. Event Mode

vb
Private WithEvents m_Delay As cDelay

Private Sub Form_Load()
    Set m_Delay = New cDelay
End Sub

Private Sub btnStart_Click()
    m_Delay.CountDown 3000  ' Triggers OnTime after 3 seconds
End Sub

Private Sub m_Delay_OnTime()
    MsgBox "Time's up!"
End Sub

2. Callback Mode

vb
Private m_Delay As cDelay

Private Sub Form_Load()
    Set m_Delay = New cDelay
End Sub

Private Sub btnStart_Click()
    ' Chainable call with multiple parameters
    m_Delay.Callback(Me, "MyFunc", "param1", 123, Now).CountDown 3000
End Sub

Public Sub MyFunc(ByVal s As String, ByVal n As Long, ByVal d As Date)
    MsgBox s & ", " & n
End Sub

3. Sync Mode

vb
Private m_DelaySync As cDelay  ' Must be module-level to allow cancellation

Private Sub btnStart_Click()
    lblStatus.Caption = "Waiting..."
    lblStatus.Refresh

    m_DelaySync.Sync().CountDown 3000  ' Wait 3 seconds, UI stays responsive

    ' Check if cancelled
    If m_DelaySync.IsCancelled Then
        lblStatus.Caption = "Cancelled"
    Else
        lblStatus.Caption = "Done!"
    End If
End Sub

Private Sub btnCancel_Click()
    m_DelaySync.Cancel  ' Cancel sync wait
End Sub

API Reference

Properties

PropertyTypeDescription
ModeDelayModeCurrent mode (read-only)
IsActiveBooleanWhether active (read-only)
IsCancelledBooleanWhether cancelled in sync mode (read-only)
DelayMsLongDelay milliseconds (read-only)

📊 Comparison Analysis: cDelay vs Native DoEvents

Methods

Callback(CallbackObject, ProcName, [ParamArray P()])

Sets callback mode.

Parameters:

  • CallbackObject - Object containing the callback method (usually Me)
  • ProcName - Callback method name (string)
  • P() - Optional parameters, up to 9

Returns: cDelay object itself (chainable)

Example:

vb
delay.Callback(Me, "ProcessData", userId, userName).CountDown(2000)

Sync()

Sets sync mode.

Returns: cDelay object itself (chainable)

Example:

vb
delay.Sync().CountDown(5000)

CountDown(Milliseconds)

Starts countdown.

Parameters:

  • Milliseconds - Delay time (milliseconds)

Notes:

  • Event/Callback mode: Returns immediately, triggers event/callback when time is up
  • Sync mode: Blocks and waits, UI stays responsive

Cancel()

Cancels the delay.

Behavior:

  • Stops timer (event/callback mode)
  • Sets cancelled flag (sync mode)
  • Clears callback info
  • Triggers OnCancel event

Events

OnTime()

Triggers when time is up (event mode only).

OnCancel()

Triggers when delay is cancelled.


Sync Mode Details

Why Module-Level Variable Required?

In sync mode, CountDown is a blocking call:

vb
' Wrong: Local variable cannot be operated during blocking
Private Sub btnStart_Click()
    Dim delay As New cDelay
    delay.Sync().CountDown(3000)  ' Blocks here!
    ' Code below executes after 3 seconds
End Sub

' Correct: Module-level variable can be accessed in other events
Private m_Delay As cDelay

Private Sub btnStart_Click()
    Set m_Delay = New cDelay
    m_Delay.Sync().CountDown(3000)  ' Blocks
End Sub

Private Sub btnCancel_Click()
    m_Delay.Cancel  ' Can cancel the wait above
End Sub

Cancellation Mechanism

vb
Private Sub btnStart_Click()
    m_Delay.Sync().CountDown(10000)  ' 10 second wait

    ' Check cancellation status
    If m_Delay.IsCancelled Then
        ' User cancelled early
    Else
        ' Completed normally
    End If
End Sub

Technical Implementation

Message Pump Principle

Sync mode uses Windows API to implement message loop:

vb
Private Declare Function PeekMessage Lib "user32" ...
Private Declare Function DispatchMessage Lib "user32" ...

Do While Not bDone
    ' Check cancelled flag
    If m_Cancelled Then Exit Do

    ' Check time
    If GetTickCount() >= EndTick Then Exit Do

    ' Process message queue
    Do While PeekMessage(uMsg, 0, 0, 0, PM_REMOVE) <> 0
        TranslateMessage uMsg
        DispatchMessage uMsg
    Loop

    Sleep 1  ' Avoid high CPU usage
Loop

Advantages over DoEvents:

  • Finer control
  • Can process specific messages
  • Avoids reentrancy issues

Automatic Lifecycle Management

First instance created

AutoInit() calls InitDelaySystem()

Reference count = 1

...

Last instance destroyed

AutoCleanup() detects count = 0

Calls TermDelaySystem() to cleanup global resources

Notes

  1. Sync mode must use module-level variable, otherwise cannot be cancelled

  2. Callback is cleared after cancellation, need to set Callback again to use

  3. Parameter passing uses Variant, callback function parameter types must match

  4. Avoid blocking in callback, otherwise will affect other timers

  5. Cleanup on form unload:

    vb
    Private Sub Form_Unload(Cancel As Integer)
        m_Delay.Cancel
        Set m_Delay = Nothing
    End Sub

FAQ

Q: Will UI still respond in sync mode?

A: Yes. The message pump processes Windows messages including mouse, keyboard, repaint, etc.

Q: Can multiple delays run simultaneously?

A: Yes. Each cDelay instance runs independently, managed through global collection. (Future: add cDelays.cls for multi-instance management with Tag)

Q: Can callback mode call private methods?

A: No. Callback methods must be Public because CallByName requires external visibility.

Q: What is the precision of sync mode?

A: Affected by Sleep 1, precision is approximately 1-15 milliseconds (depending on system scheduling).


Changelog

v1.0 (2026-03-31)

  • Initial release
  • Three modes: Event, Callback, Sync
  • Automatic lifecycle management
  • Sync mode supports cancellation

Future Feature Preview

Below are planned new delay methods at the same level as CountDown:

New Delay Methods Overview

MethodPurposeExample Scenario
ClockAtExecute at specified timeDaily 14:30 reminder
ClockAtDateSpecify date and time2026-04-01 meeting reminder
IntervalRepeating intervalCheck status every 5 seconds
RandomRandom time rangeSimulate human operations
WaitUntilExecute when condition metWait for data ready
DebounceDebounceSearch after input stops
ThrottleThrottleLimit scroll event frequency
AfterLastExecute after idleAuto save after 3 seconds idle
RetryRetry mechanismAuto retry failed network request
ScheduleMulti-timeCheck mail at 9/12/18 daily
DelayAfterDelay after eventAuto backup 5s after file modified

Code Examples

vb
' Execute at 14:30 daily
delay.ClockAt("14:30:00").RepeatDaily().Callback(Me, "DailyReport")

' Check once every 5 seconds, max 10 times
delay.Interval(5000).RepeatCount(10).Callback(Me, "CheckStatus")

' Debounce: search after 500ms of no input
delay.Debounce(500).Callback(Me, "DoSearch")

' Throttle: log at most once every 2 seconds
delay.Throttle(2000).Callback(Me, "SaveLog")

' Auto save after 3 seconds idle
delay.AfterLastInput(3000).Callback(Me, "AutoSave")

' Retry 3 times on failure, increasing interval (1s, 2s, 4s)
delay.Retry(3, 1000, 2).Callback(Me, "ConnectServer")

These features transform cDelay from a simple delay utility into a powerful scheduling system!

Roadmap: ./TODO.md

Last Updated: 2026-03-31

VB6 and LOGO copyright of Microsoft Corporation