Promotic
WikipediaLinkedInYoutubeTwitterFacebook

PmSequencer - Deatiled object description

See: Object PmSequencer
 
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 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 fires 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 fired. By this the item ends.

Further it is possible on the Type of item start configuration item to set the meaning of timeout that can be set 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 called (i.e. the same behavior as if the time expired early).

In the event onStep 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).
 
Using another thread:

On the Used thread configuration item it is possible to set the thread where the onStep event is called. 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 from 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 Promotic 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 by the Params metody PmSequencer.Add parameter. 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 (onStep event) a complementary array and transmit it as a parameter Val2 of the PmSequencer.Add method. It is also possible to transmit the data in the PmData object. Usage see An 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 (PmSequencer) implies that it is determined for the sequential control first of all but we'll show other its possibilities:
 
1.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 the PmSequencer object as follows: On the Sequencer page 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 the parameter Timeout=t1 and give the item the identification for example "A1" into the variable Val1. This means that we realize:

oSequencer.Add t1, "A1"

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

  Case "A1"
    ... algorithm of the action A1...
    pMe.Add t2, "A2"
  Case "A2"
    ... algorithm of the action A2...
    pMe.Add t3, "A3"
    ...
End Select

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).

 
2.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: 0 = items start independently, each according to its timeout. We call the Add method for all items together:

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:

  Case "A1"
    ... algorithm of the action A1...
  Case "A2"
    ... algorithm of the action A2...
    .. etc. ..
End Select

In this case the first action A1 is started immediately (or 5 seconds after starting the runtime) 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.

 
Example of the time control:

The request is to perform the first action A1 after t1 seconds and the seconds action A2 after t2 second, 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 PmSequencer object together:

oSequencer.Add t1, "A1"
oSequencer.Add t2, "A2"

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

  Case "A1"
    ... algorithm of the action A1...
  Case "A2"
    ... algorithm of the action A2...
End Select

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.

 
Example of the asynchronous control:

The request is to perform the action A1 only when for example data from communication arrive or when the operator 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 was fired - whether of the communication (pressing the key ..) 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 PmSequencer object:

oSequencer.Add t1, "A1", 111

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

We include the following statement into the script of the asynchronous event at the end of data transfer (at pressing the key ..):

oSequencer.Release 1, 2, "A1", 222

This statement means that in the PmSequencer object the item, whose variable Val1 (=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 variable Val2 (= parameter 2) of this item.

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

  Case 111
    ... algorithm of the action A1 if the timeout expired
  Case 222
    ... algorithm of the action A1 if the asynchronous event occurred
End Select

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

 
An example of time consuming process in a work thread:

There is a request to run the following algorithm: read the data from the application (object PmData)(step read), process the data (step work) and write the processed data back. 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 page 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 caling the Add method, with the "read" step identification in the Val1 parameter.

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

The onStep event for all three steps is as follows:

  Case "read"
    Dim aDataRead(100)
    ... reading the data from the application into the aDataRead array and passing the input data to another step
    pMe.Add 0, "work", aDataRead, 0, "thread:work;"
  Case "work"
    Dim aDataWrite(100)
    ... processing the input data in pEvent.Val2 to the output data in the aDataWrite array and transfering the input data to another step
    pMe.Add 0, "write", aDataWrite, 0, "thread:main;"
  Case "write"
    ... writing the input data in pEvent.Val2 into the application
End Select

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 scrip (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 PmSequencer 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.
© MICROSYS, spol. s r. o.Tavičská 845/21 703 00 Ostrava-Vítkovice