Project

General

Profile

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, the PSTimer 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).
Here are the differences:
  • 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 the Callback attribute which allows to set the callback procedure directly, instead of indirectly setting the name attribute in the CONTROL-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 if interval is set and
    • Cease - stops the timer.

© 2004-2021 Golden Code Development Corporation. ALL RIGHTS RESERVED.