- Timer Service
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.
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:
intervalis set in milliseconds;
- the scheduler is active only if
enabled = yes;
- new callback procedure can be designed while timer is active;
- setting a new
intervalwill abort the current schedule and restart timer for new value.
PSTimer extension is written on COM invocation framework, so the FWD
PSTimer will expose a virtually similar interface to the legacy
PSTimer objects can be accessed in two ways in FWD, one for each interface the object implement.
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).
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.
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
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
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, the
PSTimerobject 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
AboutBoxmethod was dropped;
FWDTimerinterface introduces the
Callbackattribute which allows to set the callback procedure directly, instead of indirectly setting the
nameattribute in the
CONTROL-FRAMEwidget. It improves the flexibility by allowing any procedure to be set instead of the constrained
- two new utility methods were added:
Start- starts the timer if
intervalis set and
Cease- stops the timer.
© 2004-2021 Golden Code Development Corporation. ALL RIGHTS RESERVED.