In Part 1 of this Optimizing Xojo Code series, we looked at a working but discouraged approach using a tight loop with DoEvents to keep the UI from freezing. In Part 2, we explored a better alternative by replacing that loop with a Timer control dragged onto a DesktopWindow. This is a simple and effective solution that takes advantage of Xojo’s object-oriented nature.
But what if you need a timer inside a Class or a Module where you can’t drop a visual control?
The Strategy: AddHandler
When you use a Timer control from the library, you double-click it to add an Action event. When we create a Timer in code, we don’t have a “code editor” for it in the same way. Instead, we use the AddHandler command to tell Xojo: “When this timer fires its Action event, run this specific method instead.”
Looking at the Code
Let’s look at how we implement this. In our example project, we have a button that initializes our timer and a separate method to handle the “ticks.”
The Setup
First, we define a property on our window (or class) to hold our timer: mWaitTimer As Timer
Then, in the Pressed event of our button, we instantiate it:
Sub Pressed() Handles Pressed
' 1. Cleanup
If mWaitTimer <> Nil Then
mWaitTimer.RunMode = Timer.RunModes.Off
mWaitTimer = Nil
End If
' 2. Initialization
mElapsedMs = 0
StatusLabel.Text = "0"
' 3. Create the dynamic timer
mWaitTimer = New Timer
mWaitTimer.Period = 100 ' 100 ms tick
mWaitTimer.RunMode = Timer.RunModes.Multiple
' 4. The Magic: Link the Action event to our WaitTick method
AddHandler mWaitTimer.Action, AddressOf WaitTick
End Sub
The Handler (Doing the Work)
Now, let’s create the method named WaitTick. Crucial Note: When using AddHandler for a Timer, the first parameter of your receiving method must be of the type Timer so it knows which object triggered it.
Sub WaitTick(t As Timer)
mElapsedMs = mElapsedMs + t.Period
If mElapsedMs >= kCountTo Then
' Achievement unlocked! Stop the timer and clean up
t.RunMode = Timer.RunModes.Off
StatusLabel.Text = "done"
' It's good practice to remove the handler when done
RemoveHandler t.Action, AddressOf WaitTick
Else
StatusLabel.Text = mElapsedMs.ToString
End If
End Sub
How It Works
- New Timer: We create a new instance of the Timer class in memory.
- AddHandler: This command connects the
Actionevent of our new timer to theWaitTickmethod. TheAddressOfoperator tells Xojo the memory location of the code we want to run. - Passing the Object: Because
WaitTickreceivest As Timeras a parameter, you can actually use the same handler for multiple different timers and knows exactly which one is calling for attention.
Wrapping Up
By moving your Timers into code, you take a significant step toward writing more modular Xojo applications. You’ve moved the logic from “Global UI state” into “Managed Code execution.”
In the upcoming Part 4, we’ll look at a shortcut that makes one-off background tasks a breeze: Timer.CallLater.
Until then, happy coding and don’t forget to add your own solution in the Xojo Forum!
Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!
Optimizing Code Series:
