GettingStarted

Timer Lesson

From Xojo Documentation

Introduction

Learn everything you need to know about the use of the Timer classes available in Xojo; including when and how to apply them to your Desktop, Web, Raspberry Pi, iOS and Console projects!

Create new Timer instances and learn how to execute them without needing instantiation; all the available classes and when you have or need to use them, depending the project. Throughout the course you will also learn how to use the Timers in a flexible way, switching the code you want to execute on the fly … even if that code has to be executed by several kinds of objects.

After this course completion, you will be able to know without a doubt when and how to use every Timer class for the best possible results! Read each section and watch the accompanying videos (in Spanish with English subtitles).

Lesson 1: Introduction to Timers

You will probably come across a situations where you want to execute code at regular time intervals; maybe because you are porting a project from other development environment (for example VisualBasic), or because you are simply discovering multi-platform programming with Xojo for first time. Throughout this lesson, you will find the answers that you need in order to use all the available classes under the Xojo framework: the Timer.

At the time of this writing, Xojo gives us the Timer in several flavours under the Classic or Modern frameworks. In addition, there is a third Timer variation: WebTimer; the one we use when we need to make use of this feature in our Web apps from the Client side (that is, from the user Web Browser), because the other two classes (Timer and Xojo.Core.Timer) are intended to work from the server side when used on a Xojo Web project. This is probably not what you want to do most of the time, because when running from the server side, the executed code is global to the app and not for every user or session. To summarize, we can currently use the following classes in our Xojo projects:

  • Timer. This is the class from the Classic Framework. You can use it in Desktop, Console, Raspberry Pi and Web projects (from the server side).
  • Xojo.Core.Timer. This is the class available for the iOS Framework. Yo can use it in iOS, Desktop, Console, Raspberry Pi and Web projects (from the server side).
  • WebTimer. This is the class you have to use in order to execute code at regular time intervals from the client side of your Web Apps. Obviously, it doesn' work under Desktop, Raspberry Pi (Desktop) Console or iOS projects.

One thing to remember when working with Timers is that they don't create new, separate, threads of execution. They use the same main thread of the Xojo App; that is, the same thread shared by the user interface to update their graphical state and being agile and responsive to the user interaction.

Thus, we should create our Timers so the code they execute doesn't require much processing time, locking the user interface responsiveness. If we need to accomplish a complex task, then we probably need to change our focus to the use of Threads in combination with Timers (if we need to update user interface components).

Lesson 2: Creating Timer Instances

In this next case, we will see how you are able to delay the code execution via the use of a Shared Method from the Xojo.Core.Timer class. All Timer instances need to maintain their scope while in use. This means that you will probably want to create your Timer instances as Properties for objects that are alive until we don't need to execute the code associated to that particular Timer. For example, some good candidates are the global App object, the particular Window they are involved with, or as part of other objects that maintain their scope during the execution of the app. Once these objects are destroyed (cleaned from memory), their associated timers will stop firing the code included into their Action Event.

As we can do with other classes, we can create new instances directly from code using the New keyword in combination with all the available Timer classes; or with the classes we create from scratch, their Super property is always set to Timer, either Xojo.Core.Timer or WebTimer.

Another option we have to create new Timer instances that maintain their scope, is dragging the available Control from the IDE Library (Controllers Section) and dropping it over the Designer Layout Editor for a particular Desktop, Web Window or iOS View. As result of that action, the IDE will add a new Timer instance to the Layout Editor tray also selectable from the Project Browser listing hierarchy.

As long the Window or View associated with the Timer instances created this way are in Scope (open, in memory), our timers will be active and running! Once we have our Timer, Xojo.Core.Timer or WebTimer instances, we need to add the Action Event to them. Here is where we write the code to be executed by the Timer. The final steps are to define the properties in charge of how and how often the Timer should be fired: Period and Mode, as you will see in the next lesson.

When we add new instances dragging the Timer control from the Library, Xojo will create them by default as instances from the Timer class for Desktop projects, WebTimer instances for Web projects and Xojo.Core.Timer for iOS Projects. If needed, you can always use the Inspector Panel to change the Super field of the instance from Timer to Xojo.Core.Timer for Desktop projects.

On the other hand, the fact that some Timer instances had been added from the Library to the Tray doesn't mean that we can't refer to them from code. In fact, we can use them the same way as if they had been directly instantiated from code. But, remember, when working with Web projects, you would probably prefer to add Timer instances by dragging them from the Library, as these are the ones that execute their code from the client side independently per session.

Lesson 3: Using Timers Without previous instantiation

Sometimes we don't need to use all the Timer functionality; in fact, there are cases where we only need to delay or fire the execution of a snippet of code one time. Why should we go through all the instantiation process just for that? Well, we don't have to if we don't want to! In these cases we can use a Shared Method from the Xojo.Core.Timer class (named Class Method in other programming languages):

Xojo.Core.Timer.CallLater(period As Integer, methodToExecute As CallNoParams)

In this method signature, period is the Timer firing time period expressed as milliseconds; while the methodToExecute parameter is the in-memory address for the method whose code we want to execute. We can obtain a Method memory address using the AddressOf or WeakAddressOf commands.

As you can see, the Type for the methodToExecute parameter is CallNoParams. This Type is a Delegate that equals any method signature that lacks of parameters in his definition. Thus, if our Window1 object had a "MyMethod" method on it, we could execute this code delayed by a second using the following fragment in the Open Event of the same Window1 object:

Sub MyMethod
MessageBox("Hello World, I'm here!")
End Sub

Sub Open
Xojo.Core.Timer.CallLater(1000, AddressOf MyMethod)
End Sub

Of course, we can also use the available Shared Method variation that allows passing a parameter to our method:

Xojo.Core.Timer.Call(period As Integer, methodToExecute As CallWithArg, parameter As Auto)

As you can see, the only change is the Delegate Type to any method that accepts receiving just one parameter of Auto Type. For example:

Sub MyMethod(parameter As Auto)
MessageBox("Hello World, I've received this message from the past: " + parameter)
End Sub

Sub Open
Xojo.Core.Timer.CallLater(1000, AddressOf MyMethod, "You will receive this one second after my execution")
End Sub

Canceling Timer execution

What if our app needs to change his mind and cancel a previously scheduled Timer execution? The Xojo framework has a Method for that too, CancelCall in the two possible Delegate type versions (with or without parameters):

CancelCall(MyMethod As CallNoParams)
CancelCall(MyMethod As CallWithArgs)

In both cases, we just need to pass along the method address whose previously scheduled execution we want to cancel. Beware of silly bugs! If you mistakenly pass the address of an existing method that has not been previously scheduled, then the Xojo.Core.Timer.CancelCall will not complain and your true scheduled method will be called as expected.

Lesson 4: Period, Mode and Activation

It doesn't matter which timer class you decide to use, they all share a couple of key Properties: Period and Mode. The first property allows us to set the firing period time expressed as milliseconds, once the timer reaches that time-period limit it will fire the code associated as the Action for the instance.

The second property, Mode, allows us to decide if the timer instance has to be fired just once or multiple times at Period set intervals. A third option is the one that allows us to stop the timer instance functionality, without destroying the instance, so we can reuse it again. The best way to set a timer mode is to use the Constant values already available for each Timer Class. For example, for Timer based instances:

  • ModeOff. The Timer is stopped.
  • ModeSingle. The Timer will fire just once.
  • ModeMultiple. The Timer will fire multiple times, regularly, at the specified Period.

So, if we would want to run a WebTimer named wt multiple times, we would use this code:

wt.mode = WebTimer.ModeMultiple

For Xojo.Core.Timer based instances, the available constants vary slightly:

  • Off. The Timer is stopped.
  • Single. The Timer will fire just once.
  • Multiple. The Timer will fire multiple times, regularly, at the specified Period.

In order to set a Xojo.Core.Timer instance named myTimer in Single Mode, we can use this code:

myTimer = Xojo.Core.Timer.Modes.Single

One thing to note is that all instances created from the Timer class have a third Property: Enabled. If we set this property using the True boolean value, then the Timer will be activated (it will start running), or you can set this property with the False boolean value in order to deactivate it. If we set the property to False and then to True, the timer instance will reset itself to the start of the period; useful if we need to reset the firing time of the associated action. By default, all the classic framework Timer instances have their Enabled property set to True.

Lesson 5: On Classic Timers

Long, long ago… the only way to execute scheduled code in Xojo was subclassing the Timer class, implementing the Action Event on it, and writing the code we wanted to execute inside such Event. That is, our code should:

  • Create an instance from our subclass,
  • Set this Period and Mode properties,
  • Optionally, set the Enabled property to True. Remember that new instances have this property already set to True by default!

That said, subclassing from Timer, Xojo.Core.Timer or WebTimer still is the best option in order to guarantee encapsulation and portability of the functionality that such specialized timers may provide into other projects.

Lesson 6: Action Event Substitution with AddHandler

As result of the Xojo framework evolution, we have additional mechanisms that simplify the use of Timers that we know only apply to the project at hand. Even better, we don't need to have previously created new subclasses in order to execute scheduled or delayed code. We just need to substitute the Action Event of the timer instance with the address of the Method we want to execute in his place. The only thing we have to observe is that the replacement method signature only includes a parameter of Timer or Xojo.Core.Timer Types.

Let's suppose we have a property named myTimer As Timer, and we want to substitute this Action Event with the MyMethod method so we can execute the associated code without the hassle of having to previously create a new class just for that. This code fragment would be enough:

Sub MyMethod(sender As Timer)
MessageBox("Hi there!")
End Sub

Event Open
myTimer = New Timer
myTimer.mode = Timer.ModeMultiple
myTimer.period = 1000
AddHandler myTimer.Action, AddressOf myMethod
End Sub

However, once we use AddHandler to assign a method address to a timer instance, we can't change it. We should destroy the instance in use, create a new one, and finally assign the new method address we want to use from that point on.

Lesson 7: Classic Timer: Notifications

When using the Timer class from the Classic Framework, we can use an additional technique: send notifications to all objects we want, as long as we have previously registered them into that particular Timer instance. To do that, these objects need to implement the ActionNotifcationReceiver Class Interface.

If in using AddHandler we can only execute code on one object, with ActionNotificationReceiver we can execute different code on different objects in the same time period; and we just need to use one Timer instance for that!

In addition this technique is also more flexible because we can subscribe or un-subscribe objects on the fly using the AddActionNotificationReceiver and RemoveActionNotificationReceiver, respectively, on the timer instance.

For example, let's suppose that we have added the ActionNotificationReceiver Class Interface to our window object (named "Window1"), using for that the Interfaces button from the Inspector. As result of that action, Xojo will automatically add the PerformAction method associated with that Class Interface. Let's write the following code for the added method:

MsgBox("I'm receiving a notification from the Timer!")

Let's change now the code for the Open Event of the window:

myTimer = New Timer
myTimer.Mode = Timer.ModeMultiple
myTimer.Period = 1000
myTimer.AddActionNotificationReceiver(Me)

As you can see, in this case we use as the method argument any object that conforms to the ActionNotificationReceiver Class Interface. The best part is that the objects, registered as observers in the timer instance, don’t need to maintain their scope anymore; the timer instance will be in charge of that until we un-subscribe them using the RemoveActionNotificationReceiver method.

Quizzes

Take these quizzes to test your knowledge of Timers. Check your answers on the Timer Tutorial Quiz Answers page.

Quiz 1: Introduction to Timers

Use this Quiz to check what you have learned about the available Timer classes and other initial considerations.

Question 1.1: What Timer class would you use in an iOS project?

  • Xojo.Core.Timer
  • Timer
  • WebTimer

Question 1.2: What Timer class would you use in a Web project, from the Server side?

  • Xojo.Core.Timer
  • WebTimer
  • Timer

Question 1.3: Can a Timer can update the user interface controls?

  • Yes
  • No

Question 1.4: Can a Timer add its own execution thread?

  • Yes
  • No

Question 1.5: Can a Timer code execution lock the user interface events?

  • Yes
  • No

Quiz 2: Creating Timer Instances

This quiz lets you review what you have learned about timer instantiation, in relation with every kind of project, and the available options at your disposal.

Question 2.1: Generally speaking, what are the main steps involved in making a Timer functional?

  • Create a instance.
  • The Timer has to be part of the object.
  • The instance has to maintain its Scope along the execution.
  • The Timer has to be always linked to a Window.

Question 2.2: Do you have to create all the Timer from code?

  • No, you can add a Timer to a Layout from the Library.
  • Yes

Question 2.3: Can I modify a Timer instance added from the Library?

  • Yes
  • No
  • It depends on the type of timer.

Question 2.4: In what class are the Timers from the Library based?

  • WebTimer
  • Xojo.Core.Timer
  • Timer
  • It depends on the type of project.

Question 2.5: For a Console project, what class is a Timer added form the Library based upon?

  • ConsoleTimer
  • Timer -- you always drop it in the Project Browser.
  • Xojo.Core.Timer

Quiz 3: Using Timers without previous instantiation

Put in practice the knowledge acquired in this lesson, specifically about using Timers without previous instantiation.

Question 3.1: It is possible to run a Timer without instantiation when using the classic framework?

  • Yes
  • No

Question 3.2: How many parameters can we pass along the Xojo.Core.TimerCallLater method?

  • As many as we want!
  • One
  • None
  • None or One

Question 3.3: Can we use Xojo.Core.Timer.CallLater in the frontend side of a Web app?

  • Of course! In fact this is the recommended option!
  • Just if we want to update the user interface controls.
  • No, this Timer only is used from the server side.

Quiz 4: Period, Mode and Activation

Put in practice the knowledge acquired in this lesson, specifically Timers Modes and the way we can set the firing time period.

Question 4.1: The Timer period is set in…?

  • Microseconds
  • Seconds
  • Milliseconds
  • It depends of the Target

Question 4.2: Do you have to set the Mode property to activate the Timer?

  • Yes
  • No
  • It depends of the Event we have used to set the Timer

Question 4.3: Can the Timers set on the front end of a web app be fired just once?

  • Yes
  • No

Quiz 5

There is no quiz for lesson 5.

Quiz 6: AddHandler

This quiz lets you review what you have learned about the use of AddHandler in order to substitute the default Action event.

Question 6.1: Does AddHandler allows passing an object as argument?

  • No
  • Yes, but it should be a Delegate.
  • No, it has to be a Method with Delegate signature.

Question 6.2: Can you use AddHandler to substitute the Action Event just one time for every Timer instance?

  • No. We can re-assign the method as many times we need.
  • We can re-assign just between timer action events.
  • Yes, but we need to create a new instance in first place.

Question 6.3: The method signature we assign as Action substitute has parameters?

  • Yes
  • No
  • It depends, we choose!
  • Always, using a Timer or Xojo.Core.Timer type
  • Always, using a Timer, Xojo.Core.Timer or WebTimer type.

Quiz 7: Class Interface

Verify what you have learned about the use of the Class Interface that allows the Timers sending notifications to other objects

Question 7.1: With the notifications use, do we achieve that several objects can run their respective code for each Timer interval?

  • Yes
  • It is optional, we can register just one object.
  • No, we can register just one object.
  • Yes, but they need to be different kind of objects, running the all the same code!

Question 7.2: What Class Interface do we have to implement in the objects?

  • TimerActionObserver
  • TimerActionReceiver
  • ActionNotificationReceiver
  • ActionNotificationTimer
  • NotificationReceiver

Question 7.3: Can we use this Class Interface in combination with Xojo.Core.Timer?

  • Of course! In fact, this is the recommended way.
  • Always, they are the only kind of Timers used along the app or a particular Module Scope.
  • No

Refer to the Timer Lesson Quiz Answers