Timer Service¶
Introduction¶
This is a replacement for the PSTimer OCX included in the 4GL. The implementation was first done in #1818 (FWD v3.x and before) and then it was refined in #3769 (FWD v4.0). The support is complete but the implementation can be refined (see #5115 and #5254).
The idea is that this is a non-visual OCX that will fire a callback procedure when a configurable timer pops (i.e. on each tick of the timer). It is not clear why this is an OCX instead of a core feature of the 4GL.
4GL Legacy¶
Progress 4GL does not provide an internal solution for scheduling tasks at a fixed interval. Instead, it bundles a timer service in the form of an ActiveX object, making the solution available only for applications running on Windows OS. Because of the overhead of loading the ActiveX, the operation is statically hardcoded by Progress App Builder application.
FWD Implementation Details¶
FWD is a cross-platform application and avoids the use the old ActiveX technology. Instead FWD offers a timer service written in pure java. This makes pieces of code that were limited to run only on Windows in 4GL to be also available on other platforms after FWD conversion. From the behavioural point of view, the FWD solution is identical to PSTimer Activex:- the
interval
is set in milliseconds; - the scheduler is active only if
enabled = yes
; - new callback procedure can be designed while timer is active;
- setting a new
interval
will abort the current schedule and restart timer for new value.
The PSTimer
extension is written on COM invocation framework, so the FWD PSTimer
will expose a virtually similar interface to the legacy PSTimer
.
The PSTimer
objects can be accessed in two ways in FWD, one for each interface the object implement.
Using the ComObject
interface.¶
This is the legacy mode, the way the converted code accesses PSTimer
objects. All code is converted, including the management of the invisible CONTROL-FRAME
widget. As in legacy 4GL, objects are accessed using a COM-HANDLE
variable. The only way to acquire it is using the COM-HANDLE
attribute of a CONTROL-FRAME
. You can communicate with a PSTimer
object by accessing the COM-properties and COM-methods.
Common code like
DEFINE VARIABLE myCOM AS COM-HANDLE NO-UNDO. myCOM = CtrlFrame:COM-HANDLE. myCOM:PSTimer:INTERVAL = 5 * 1000. v1 = myCOM:PSTimer:ENABLED.
is converted into following java code:
comhandle myCom = TypeFactory.comhandle(); myCom.assign(ctrlFrame.unwrapControlFrame().getComHandle()); myCom.chain("PSTimer").setProperty("INTERVAL", multiply(5, 1000)); v1.assign(myCom.chain("PSTimer").getProperty("ENABLED"));
This mode is discouraged and is provided to allow conversion in the absence of the extension hints (see below).
Using the FWDTimer
interface¶
Objects are accessed using a HANDLE
variable. They are created using the special syntax available in PSTimer FWD extension:
DEFINE VARIABLE th AS HANDLE. CREATE TIMER th ASSIGN INTERVAL = 1000 ENABLED = yes CALLBACK = "Timer-Tick" END.
A PSTimer
object can be handled using its attributes and methods, the same way like a standard widget. This is the preferred way to manually write code that access the FWD timer service.
To instruct the conversion to use this mode, there is a special step when converting 4GL code that loads PSTimer
ActiveX-es. The Progress App Builder application uses a dedicated file type (*.wrx
) to store the initial values of the ActiveX properties. Because the file is binary, FWD cannot use it. Instead a xml text file is used to pass the initial values to FWD conversion. The values will be hardcoded into generated java sources. The ext-hints
file has the following syntax:
<extension> <wrx-section <wrx-section name="CtrlFrame" com-type="PSTimer"/> </extension>
For each timer, (in case there are multiple PSTimer instances within the same procedure) the contained wrx-section
is declared. The interval
and enabled
initial properties must be extracted from *.wrx
and assigned in 4GL code (use FWD-VERSION
preprocessor variable to make the assignment only in FWD). Since the *.wrx
file is not needed in the converted application and it is typically not deployed, make sure the call to searchPath
is removed, again with the help of FWD-VERSION
.
After conversion, the code for a timer with the above hints will look like this:
chCtrlFrame.assign(ctrlFrame.unwrapControlFrame().getComHandle()); uibS.assign(chCtrlFrame.call("LoadControls", ComParameter.input(ocxfile), ComParameter.input("PSTimer"))); chCtrlFrame.chain("PsTimer").setProperty("interval", new integer(1000)); chCtrlFrame.chain("PsTimer").setProperty("enabled", new logical(true));
As expected, the timer is active from the moment of creation (enabled = yes
) and will asynchronously call CtrlFrame.PSTimer.Tick
procedure each second (interval = 1000
).
Although the syntax for these objects is similar:
th:INTERVAL = 3000. v1 = th:ENABLED.
in the converted code the unwrapping specific to the extension is clearly visible:
chCtrlFrame.chain("PsTimer").setProperty("interval", new integer(1000)); v1.assign(chCtrlFrame.chain("PsTimer").getProperty("enabled"));
Exposed interface¶
Although the FWD Timer Extension accesses timer much like the 4GL accesses the bundled ActiveX, thePSTimer
object does not expose the exact interface. The common properties are the most important and are not changed from the legacy:
interval
- (expressed in milliseconds) sets the time interval between two calls to callback procedure. If set to 0 the timer is disabled.enabled
- sets whether the timer is active. If not active, the timer will not fire (call the designed callback procedure).
- the management of the CONTROL-FRAME was dropped. This has the benefit of reducing the clutter in the generated code;
- and useless
AboutBox
method was dropped; FWDTimer
interface introduces theCallback
attribute which allows to set the callback procedure directly, instead of indirectly setting thename
attribute in theCONTROL-FRAME
widget. It improves the flexibility by allowing any procedure to be set instead of the constrained<CtrlFrameName>.PSTimer.Tick
;- two new utility methods were added:
Start
- starts the timer ifinterval
is set andCease
- stops the timer.
© 2004-2021 Golden Code Development Corporation. ALL RIGHTS RESERVED.