Difference between revisions of "Yet another Running Timer"

From Free Pascal wiki
Jump to navigationJump to search
Line 54: Line 54:
 
=== Downloads ===
 
=== Downloads ===
 
Have a look at "https://sourceforge.net/projects/controltimer/files/"
 
Have a look at "https://sourceforge.net/projects/controltimer/files/"
 +
 +
=== Test Program ===
 +
A picture: [[Image:testprogram.jpg]]

Revision as of 17:01, 14 March 2014

Template:Yet another Running Timer

About

The first goal for this timer is to fire an event when a certain amount of time has elapsed. For most of the cases the already existing TTimer component will be fairly enough. But it requires the LCL and when threads are involved, things may change.

A second reason why to implement a new timer is the way the TTimer processes properties when they change and specially when the Enabled property is set. Whenever any property changes, the current timer object is destroyed and re-created, which could be a time and resources consuming process.

Another reason is to get rid of the multi thread limitation with the TFPTimer used as a timer replacement where the LCL is not available (like in a service). The TFPTimer uses a synchronize method to fire the timer event which limits its usage to the main thread only, as the TFPTimer uses an internal thread.

For these reasons I decided to make a new timer control, based somewhat on the TFPTimer but without the threads limitation.

As is, the number of active timers depends on the number of threads supported by the runtime platform.

Author

Antonio Fortuny

Description

The timer itself is a TComponent descendant but inside there is a thread which actually does the job. The timer does not rely on any other component the basic TComponent excepted.

Once created, the timer will continuously run a thread and count the elapsed time form the start by steps of 10 ms. As a matter of fact, the accuracy of the timer seems to be around a couple of ms within a range of a few seconds. This is why I do not recommend it for time critical operations unless the accuracy is acceptable. Another lack is that the timer relies on the GetTickCount system function. As far as I now this function returns the number of elapsed ms from the last system boot. As the return value is a DWORD, the maximum value is a 32 bit integer. So the value will return to 0 after almost 48 days. This could lead to potential timing errors.

One immediate improvement could be how to break this 48 days barrier without adding new time critical penalties.

Implementation

The timer is implemented using a single unit. However, because IDE users like to use and drop non visual components as well, a package has been made to wrap the main unit and have a TSimpleTimer descendant which can be installed in the Lazarus IDE.

The timer thread is driven by the means of an Enabled property and an event. When enabled, the event is set and the timer runs continuously. On each loop it waits for 10 ms. When entering the disabled state it waits 500 ms for the event to be set. This means that in disabled state, the timer it is almost "invisible".

This component was designed for cross-platform applications and was written specifically for the Lazarus IDE and Free Pascal Compiler and includes a demo application.

Platforms

The timer runs without problems on Win32, Win64, Linux x86_64 (OpenSuse 12, Ubuntu). It could maybe run on other platforms, testers are welcome.

Operations

The operations interface has been made deliberately as simple as possible: One time interval to be checked, One Active property to check whether the timer is active or not An Enabled property to start (True) and stop (False) the timer One event to be fired when the interval is exhausted and of course a constructor and a destructor. That's all.

The point on which the user should take care is the event which will be fired. Because the timer does not care about the context in which the event code has been written, there is a potential error situation from the application point of view: all the code inside the event will be executed in the context of the timer thread. This means that the user should be aware of multi-threading programming rules.

About multi-threading you could read the Lazarus wiki page about the subject. "http://wiki.freepascal.org/Multithreaded_Application_Tutorial"

It is not recommended to use the same timer event code for multiple timers for obvious reasons. Read the article above on how protect code against multi threading.

Downloads

Have a look at "https://sourceforge.net/projects/controltimer/files/"

Test Program

A picture: testprogram.jpg