Promotic
WikipediaLinkedInYoutubeTwitterFacebook

PmaSequencer - Deatiled object description

See: the PmaSequencer object.
 

The principle of the object:

Into the object it is possible to add so-called items, which are data structures with 3 user variables Val1, Val2 and Val3. Adding the item is carried out by the Add method. The item that is added into the object is inserted into the item queue of this object and it waits for the required time in this queue (see the Timeout parameter parameter in the Add method, the required time can be zero or infinite long). After the required time expiration the item is removed from the queue and the onStep event is triggered for this item. In parameters of this event it is possible to find out (from variables pEvent.Val1, pEvent.Val2 and pEvent.Val3) for which item the event has been triggered. By this the item ends.

Further in the "Type of item start" configurator it can be set the meaning of timeout that is entered in the Add method. It can be defined if the required timeout is the time between inserting the item and its starting (i.e. Items starts independently) or if the timeout is the delay between starting this item and previously started items (i.e. Items starts sequentially).

The item waiting in the queue can be prematurely terminated (i.e. before its time expires) by the Release or Remove method:

- The Release method removes the item from the queue and then the onStep event is triggered (i.e. the same behavior as if the time expired early).

In the onStep event it is possible to set pEvent.ReleaseCancel=true and this way prevent removal from queue - this way it is possible to call one item in the queue multiple times.

- The Remove method causes that the item is removed from the queue without invoking the event (i.e. it behaves as if no item existed).
 

The usage of another thread:

In the "Used thread" configurator it is possible to set the thread where the onStep event is triggered. It is possible to set either the main thread or to create new working thread for this object, see How to start selected scripts in another thread.

Caution! If another thread is used, then an access to other objects in the script proceeds in other than the main thread and it is necessary to take into account possible problems with the synchronization on reading and writing into Pma objects. This option is suitable first of all for time consuming calculations on the background.

 
The problem with synchronization (consistency) of read and write of the data (when using a single thread) can be solved by several ways.

One of the basic procedures is to divide the whole procedure into three steps. Read the data from the application, process the data and write the output data into the application (each step is initialised by the onStep event). The read and write step may be assigned to the main thread (preventing the data synchronization problem) and the data processing step can be assigned to the work thread. The assigning of processes to threads can be defined in the Params parameter of the PmaSequencer.Add method. The data read and write then runs in the main thread and data procesing runs in the work thread not delaying the main thread. The processed data must be transmitted between each step. The easiest way of data sharing is to create in the script of the step (the onStep event) a complementary array and transmit it as a Val2 parameter of the PmaSequencer.Add method. It is also possible to transmit the data in the PmaData object. The usage see The example of time consuming process in a work thread.

 
From the above described simple principle it is possible to construct a few structures that are preferably used for the sequential, time or asynchronous control. From the object name (PmaSequencer) implies that it is determined for the sequential control first of all but we'll show other its possibilities:
 

1st example of the sequential control:

The request is to execute the following algorithm:

- wait for t1 seconds, then perform the action A1
- wait for t2 seconds, then perform the action A2, etc.

This can be done by means of the PmaSequencer object as follows:

- On the "Sequencer" tab of the object we select Type of item start=0 = items start independently, each according to its timeout.
- Then we call the Add method with parameter Timeout=t1 and give the item the identification for example "A1" into the Val1 variable. This means that we realize:
JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(t1, "A1");

After t1 seconds the onStep event is triggered in which we perform the action A1 and then insert new time request for the action A2. It means that in the onStep event can be for example the following script:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val1)
{
case "A1":
//algorithm of the action A1
pMe.Add(t2, "A2");
break;
case "A2":
//algorithm of the action A2
pMe.Add(t3, "A3");
break;
case "A3":
//...
break;
}

By this we can create a sequence of any length by the action that can be even conditional (e.g. under certain conditions the action A2 isn't performed after the action A1 but immediately the action A3 is performed). The advantage is that we have all actions in one script (in the onStep event) and thus the whole overview sequence can be seen. In transitions between actions it is possible to store internal states into variables Val2 and Val3 (they are not used in the example).

2nd example of the sequential control:

The request is to perform 4 actions (A1,A2,A3,A4) but in the midst of their execution must be 5 seconds delay.

It is similar as in the previous example but we create it with the Type of item start: 1 = items start chronologically, timeout is delay between them.

We call the Add method for all items together:

JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(5, "A1");
oSequencer.Add(5, "A2");
oSequencer.Add(5, "A3");
oSequencer.Add(5, "A4");

and then there can be simpler script in the onStep event:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val1)
{
case "A1":
//algorithm of the action A1
break;
case "A2":
//algorithm of the action A2
break;
case "A3":
//...
break;
}

In this case the first action A1 is started immediately (or 5 seconds after starting the application) because the previous item doesn't exist and thus starting time of the previous item is set to runtime starting time. But the next items are started in 5 seconds periods in sequence.

3rd An example of the sequential control with managed item release:

It is requested to perform 2 actions (A1,A2) but there must be a security pause between them up to 10 seconds. The pause will be shortened once the first action is completed.

Type of execution will be: 1 = items start chronologically, timeout is delay between them.

We call the Add method for all items together:

JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(0, "A1");
oSequencer.Add(10, "A2");

and then there can be simpler script in the onStep event:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val1)
{
case "A1":
//algorithm of the action A1
pEvent.ReleaseCancel = true;
break;
case "A2":
//algorithm of the action A2
break;
}

In this case the 1st action A1 is started immediately. The next item is executed after 10 seconds, but it can be executed sooner, if the Release method is called after the first item is finished successfully:

JavaScriptVBScriptSelect and copy to clipboard

//algorithm of the action A1
oSeq.Release(10, 0);

The example of the time control:

The request is to perform the first action A1 after t1 seconds and the seconds action A2 after t2 seconds, etc. We do it as follows: The Type of item start is set to 0 = items start independently, each according to its timeout and we insert both actions into the PmaSequencer object together:
JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(t1, "A1");
oSequencer.Add(t2, "A2");

Then in the onStep event for example the following script can be:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val1)
{
case "A1":
//algorithm of the action A1
break;
case "A2":
//algorithm of the action A2
break;
}

It is similar to the sequential control with the difference that the actions are independent of each other but each one is performed separately. Again the variables Val2 and Val3 that could be used as additional action parameters, were not used in the example.

The example of the asynchronous control:

The request is to perform the action A1 only when for example data from the communication arrive or when the user presses the specified key, or ..., in short when an asynchronous operation happens. We don't want to wait for the asynchronous operation for infinite time but only for t1 seconds at the most. In action A1 we want to distinguish by what reason it is triggered - whether of the communication (after pressing the button ..) or of the time expiration. We do it as follows:

The type of item start is set to 0 = items start independently, each according to its timeout and we insert the item for the action A1 into the PmaSequencer object:

JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(t1, "A1", 111);

By this the item, whose the Val1 variable is the text "A1" and the Val2 variable is the number 111, is inserted into the object.

We include the following command into the script of the asynchronous event at the end of data transfer (after pressing the button ...):

JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Release(1, 2, "A1", 222);

This command means that in the PmaSequencer object the item, whose the Val1 variable (=parameter 1) equals the text "A1", have to be released and by this releasing the number 222 (which re-writes the number 111 set previously) has to be assigned into the Val2 variable (= parameter 2) of this item.

Then in the onStep event for example the following script can be:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val2)
{
case 111:
//algorithm of the action A1 If the timeout expired
break;
case 222:
//algorithm of the action A1 If the asynchronous event occurred
break;
}

In this example we basically didn't need the indication about the action A1 (i.e. the text "A1" in the Val1 variable). The example can be generalized so that the PmaSequencer object could process more asynchronous actions and then we would have to distinguish in the onStep event even according to the value of the Val1 variable.

The example of time consuming process in a work thread:

There is a request to run the following algorithm:
- prepare and pass the data (step "read")
- time consuming processing of the data (step "work") - for example: file operations
- use (write) the processed data in the application (step "write")
JavaScriptVBScriptSelect and copy to clipboard

oSequencer.Add(0, "read", 0, 0, "thread:main;");

The onStep event for all three steps is as follows:

JavaScriptVBScriptSelect and copy to clipboard

switch (pEvent.Val1)
{
case "read":  //executed in the main theread
//preparation and creation of array of files aDataRead and passing it for processing to the next step
var aDataRead = Pm.CreatePmArray().Array1("Glob.ini", "Cfg1.ini", "Cfg2.ini", "Cfg3.ini");

pMe.Add(0, "work", aDataRead, 0, "thread:work;");
break;
case "work":  //executed in the work theread
//processing the input data in pEvent.Val2 to the output data in the aDataWrite array and transfering the input data to another step
var aFiles = pEvent.Val2;
var nFiles = aFiles.GetSize(1);
var aDataWrite = Pm.CreatePmArray(nFiles);
var i;
for (i = 0; i < nFiles; i++)
aDataWrite.SetItem(Pm.IniFileRead("#cfg:" + aFiles.GetItem(i), "MySettings", "value", 0, 4), i);

pMe.Add(0, "write", aDataWrite, 0, "thread:main;");
break;
case "write":  //executed in the main theread
//writing the input data in pEvent.Val2 into the application
var aValues = pEvent.Val2;
var val1 = aValues.GetItem(0);
//...
break;
}

The read and write is to be done in a secure way from the data synchronization point of view (using the main thread), while the complex data processing is to be completed on the background in another thread (application optimalization). On the "Sequencer" tab of the object you select Type of item start=1 = items start chronologically, timeout is delay between them, and then select Used thread=Normal = new working thread of the normal priority. The request for the first step (main thread) is created by calling the Add method, with the "read" step identification in the Val1 parameter.

This way we can create a sequence of any number of steps where each step can be assigned to main or to work thread. The main advantage is that all the steps are included into a single script (in the onStep event) and the whole sequence is therefore seen on one place. When passing from one step to another, it is possible to save the inner states into the Val2 and Val3 variables.

 
The above mentioned examples show how to use the PmaSequencer object. It is possible to create even mixed controls, for example to wait hard between actions A1 and A2 for t1 seconds, to wait between actions A2 and A3 for data acceptance and consequently run the parallel actions A3 and A4 after t3 and t4 seconds, etc.
PROMOTIC 9.0.13 SCADA system documentation - MICROSYS, spol. s r.o.

Send page remarkContact responsible person
© MICROSYS, spol. s r. o.Tavičská 845/21 703 00 Ostrava-Vítkovice