cDelay Delay Object Development Documentation
'===========================================================================
' 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
OnTimeevent - 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 formFeatures
- ✅ 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
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 Sub2. Callback Mode
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 Sub3. Sync Mode
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 SubAPI Reference
Properties
| Property | Type | Description |
|---|---|---|
Mode | DelayMode | Current mode (read-only) |
IsActive | Boolean | Whether active (read-only) |
IsCancelled | Boolean | Whether cancelled in sync mode (read-only) |
DelayMs | Long | Delay 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 (usuallyMe)ProcName- Callback method name (string)P()- Optional parameters, up to 9
Returns: cDelay object itself (chainable)
Example:
delay.Callback(Me, "ProcessData", userId, userName).CountDown(2000)Sync()
Sets sync mode.
Returns: cDelay object itself (chainable)
Example:
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
OnCancelevent
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:
' 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 SubCancellation Mechanism
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 SubTechnical Implementation
Message Pump Principle
Sync mode uses Windows API to implement message loop:
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
LoopAdvantages 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 resourcesNotes
Sync mode must use module-level variable, otherwise cannot be cancelled
Callback is cleared after cancellation, need to set
Callbackagain to useParameter passing uses Variant, callback function parameter types must match
Avoid blocking in callback, otherwise will affect other timers
Cleanup on form unload:
vbPrivate 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
| Method | Purpose | Example Scenario |
|---|---|---|
| ClockAt | Execute at specified time | Daily 14:30 reminder |
| ClockAtDate | Specify date and time | 2026-04-01 meeting reminder |
| Interval | Repeating interval | Check status every 5 seconds |
| Random | Random time range | Simulate human operations |
| WaitUntil | Execute when condition met | Wait for data ready |
| Debounce | Debounce | Search after input stops |
| Throttle | Throttle | Limit scroll event frequency |
| AfterLast | Execute after idle | Auto save after 3 seconds idle |
| Retry | Retry mechanism | Auto retry failed network request |
| Schedule | Multi-time | Check mail at 9/12/18 daily |
| DelayAfter | Delay after event | Auto backup 5s after file modified |
Code Examples
' 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