PC SOFT

ONLINE HELP
 WINDEVWEBDEV AND WINDEV MOBILE

Home | Sign in | English EN
This content has been translated automatically. Click here to view the French version.
  • Overview
  • Principle
  • How to proceed?
  • Principle
  • Create and run a parallel task
  • MyParallelTask keyword
  • Wait for the execution of the task and retrieve the return value
  • Managing the sequence of parallel tasks
  • Handling the controls from a parallel task
  • Example: Accelerating the processes
  • Accelerating the processes: statistical calculation
  • Example: Improving the reactivity of application
  • Improving the reactivity of application
  • Updating the GUI via a continuation task
  • Updating the GUI via a procedure run in the main thread
WINDEV
WindowsLinuxUniversal Windows 10 AppJavaReports and QueriesUser code (UMC)
WEBDEV
WindowsLinuxPHPWEBDEV - Browser code
WINDEV Mobile
AndroidAndroid Widget iPhone/iPadApple WatchUniversal Windows 10 AppWindows Mobile
Others
Stored procedures
Overview
The computers are becoming more and more powerful. The computers have powerful processors with several cores.
To improve the performances of applications and to work with a maximum number of computer cores, you now have the ability to divide the processes into a list of sub-processes (called tasks) and to run them in parallel rather than sequentially.
A task is a procedure to run that can expect parameters and that can return a result. These tasks will be run by the computer in one or more threads according to the computer availability.
A task can be divided into several sub-tasks.
What is the benefit of parallel tasks?
The parallel tasks are useful to:
  • speed up the process time of application via the parallelism: several processes are run in parallel instead of being run sequentially: the application speed is improved.
    A simple example: start a statistical calculation for sending and receiving emails on each email address of the database. If the statistical calculation on an email address takes one second and if the database contains 200 000 email addresses, the calculation takes more than two days.
    To go faster, you have the ability to start a parallel task for each email address found.
    This example is presented in Example: Accelerating the processes.
  • improve the reactivity of the application: several long and locking processes are run in parallel instead of being run sequentially: the user does not feel that he is stuck.
    A simple example: A Table control displays a list of contacts whose photo is loaded from an Internet address. For each contact, the application preforms an Internet request (that triggers a slow down).
    In order for the Table control to be filled without being locked, the process for row display starts a parallel task used to start the Internet request and to refresh the GUI if necessary.
    This example is presented in Example: Improving the reactivity of application.
Versions 23 and later
Java This feature is now available for Java applications.
Android Widget This feature is now available in Android Widget mode.
Android This feature is now available for Android applications.
New in version 23
Java This feature is now available for Java applications.
Android Widget This feature is now available in Android Widget mode.
Android This feature is now available for Android applications.
Java This feature is now available for Java applications.
Android Widget This feature is now available in Android Widget mode.
Android This feature is now available for Android applications.
Principle
To manage the parallel tasks, WLanguage proposes:
  • a ParallelTask variable. This type of variable is used to handle a parallel task. This type of variable cannot be used to modify the characteristics of a parallel task.
  • functions for managing tasks (ParallelTask*).
Remark: You also have the ability to use the Description of ParallelTask variable. This type of variable can only be used to describe a parallel task. Once the parallel task is defined, its characteristics cannot be modified.
How to proceed?

Principle

To implement a management of parallel tasks, you must:
  1. Create and run a parallel task.
  2. Wait for the execution of the task and retrieve the return value.
  3. Manage (if necessary) the sequence of parallel tasks.
  4. Handle (if necessary) the controls from a parallel task.

Create and run a parallel task

A parallel task must be associated with a ParallelTask variable.
Several methods can be used to declare a ParallelTask variable:
  • Simple declaration. The parallel task is described during its execution with ParallelTaskExecute:
    // Déclare une variable pour manipuler une tâche parallèle
    t is ParallelTask
    // Exécution et description de la tâche parallèle
    t = ParallelTaskExecute(Proc, ("Premier paramètre", 2))
  • Declaration and description of the parallel task. Then, the parallel task is run by ParallelTaskExecute.
    // Construit une tâche parallèle
    t is ParallelTask(Proc, ("Premier paramètre", 2))
    // Déclenche l'exécution de la tâche parallèle
    ParallelTaskExecute(t)
Remark: When describing the parallel task, you have the ability to specify:
  • the procedure to run.
  • the parameters expected by the procedure.
  • the runtime mode of parallel task: management of HFSQL contexts and interactions with the main thread.

MyParallelTask keyword

MyParallelTask is used to manage the current parallel task and find out its properties. This allows you to access information about the current parallel task in the code executed by a parallel task. The accessible properties are those of ParallelTask variables:
Property nameType usedEffect
CanceledBoolean
  • True if the task is canceled,
  • False otherwise.
This property is available in read-only.
StateInteger constantTask status:
  • ptsCanceled: the parallel task is canceled (ParallelTaskCancel).
  • ptsCancelationRequested: a cancelation request was performed on the parallel task (ParallelTaskRequestCancelation).
  • ptsWaitingExecution: the parallel task is waiting to be run.
  • ptsWaitingPrevious: the parallel task waits for the execution of a previous parallel task.
  • ptsExecutionInProgress: the parallel task is currently run.
  • ptsNotScheduled: the parallel task is not scheduled.
  • ptsCompleted: the parallel task is ended.
This property is available in read-only.
IdentifierIntegerIdentifier of task. This identifier can be used for debugging purpose for example.
This property is available in read-only.
CompletedBoolean
  • True if the task is completed,
  • False otherwise.
This property is available in read-only.
ReturnedValueValue returned by the task. Caution:
  • If the task is still in progress, the ReturnedValue property waits for the end of the task
  • If the task is completed without fatal error, the property returns the return values of the procedure of the task.
This property is available in read-only.

Wait for the execution of the task and retrieve the return value

Several parallel tasks can be started at the same time. You have the ability to wait for the execution of one or more parallel tasks before running a process:
Versions 20 and later
ParallelTaskWait
New in version 20
ParallelTaskWait
ParallelTaskWait
Waits for the execution of a parallel task.
Versions 20 and later
ParallelTaskWaitAll
New in version 20
ParallelTaskWaitAll
ParallelTaskWaitAll
Waits for the end of execution of all parallel tasks found in an array.
The Property ..ReturnedValue of the ParallelTask variable type allows to know the value returned by the Procedure executed by the parallel task.
Caution: This value is available only if the parallel task is ended. If the task is in progress, the call to this property is locking until the end of the task.

Managing the sequence of parallel tasks

Several parallel tasks can be started at the same time. You have the ability to define the sequence of parallel tasks: a task can wait for the end of execution of one or more tasks before it is run. The following functions are used to define a continuation task:
Versions 20 and later
ParallelTaskExecuteAfter
New in version 20
ParallelTaskExecuteAfter
ParallelTaskExecuteAfter
Indicates a continuation parallel task that will be run when one of the specified parallel task is ended.
Versions 20 and later
ParallelTaskExecuteAfterAll
ParallelTaskExecuteAfterAll
Indicates a continuation parallel task that will be run when all the tasks found in an array of parallel tasks are ended.
Versions 20 and later
ParallelTaskExecuteAfterOne
ParallelTaskExecuteAfterOne
Indicates a continuation parallel task that will be run once the first task is ended in an array of parallel tasks.
Remark: In a continuation task, you can:

Handling the controls from a parallel task

You cannot act on the interface from a parallel task. Therefore, you cannot assign a control, fill a Table or Looper control.
Only a task defined by the ptoMainThread constant can be run in the main thread and can update the controls if necessary.
Remark: It is also possible to use the ExecuteMainThread function to execute a specific display Procedure from the parallel task.
These two methods are used in the Improving the reactivity of application example presented in this page.
Example: Accelerating the processes

Accelerating the processes: statistical calculation

An application is using the CalculateStatEmailAddress procedure to perform statistical calculations about the send and receive operations on each email address found in CUSTOMER file. This procedure takes the email address in parameter and it calculates all the statistics for this address.
If the statistical calculation on an email address takes one second and if the database contains 200 000 email addresses, the calculation takes more than two days (200 000 seconds).
To go faster, you have the ability to start a parallel task for each email address found.
Code sample:
  • Initial code (before using parallel tasks):
    nAdressesEnErreur is int
     
    HourGlass(True)
    ChronoStart()
    // Parcours la liste des clients
    FOR EACH Client
    // Lance le calcul de statistiques sur son adresse email
    IF CalculeStatAdresseEmail(Client.Email, 1) = False THEN
    nAdressesEnErreur++
    END
    END
    HourGlass(False)
    LIB_Résultat_1 = StringBuild("Résultat: %1 adresses en erreur", nAdressesEnErreur)
    Info("Traitement terminé", DurationToString(ChronoEnd(), "MMm SSs CCC"))
  • Code thai is using the parallel tasks:
    nAdressesEnErreur is int
    tabTâches is array of ParallelTask
    UneTâche is ParallelTask
     
    HourGlass(True)
    ChronoStart()
    // Parcours la liste des clients
    FOR EACH Client
    // Lance le calcul de statistiques sur son adresse email à l'aide d'une tâche parallèle
    UneTâche = ParallelTaskExecute(CalculeStatAdresseEmail, ...
    (Client.Email, 1), ptoLightCopyHFSQLContext)
    // Mémorise cette tâche dans un tableau
    Add(tabTâches, UneTâche)
    END
     
    // Attend la fin de l'exécution des tâches
    ParallelTaskWaitAll(tabTâches)
    HourGlass(False)
     
    // Parcours les tâches
    FOR EACH UneTâche OF tabTâches
    IF UneTâche.ReturnedValue = False THEN
    nAdressesEnErreur++
    END
    END
    LIB_Résultat_2 = StringBuild("Résultat: %1 adresses en erreur", nAdressesEnErreur)
    Info("Traitement terminé", DurationToString(ChronoEnd(), "MMm SSs CCC"))
Example: Improving the reactivity of application

Improving the reactivity of application

A Table control displays a list of contacts whose photo is loaded from an Internet address. For each contact, the application preforms an Internet request (that triggers a slow down).
To improve the reactivity of application and to get a smooth GUI, a parallel task is started in the process for displaying a row of Table control. This parallel task:
  • receives the contact identifier in prameter.
  • performs the Internet request to get the image.
  • retrieves the image.
  • calls a function to update the Table control.
Let's see two different codes for this example: these two codes present two different methods for updating the GUI:

Updating the GUI via a continuation task

The interface update not being possible from a parallel task run in the main thread, a specific continuation task for the display is implemented by ParallelTaskExecuteAfter. One of the parameters passed to the continuation task corresponds to the value returned by the main parallel task. To specify this parameter, all you have to do is use the ReturnedValuePreviousTask keyword.
Code sample:
  • Code for displaying a table row:
    // Si la photo n'est pas encore renseignée
    IF COL_Photo ~= "" THEN
    // Positionne l'image de sablier en attendant de récupérer la photo depuis "Internet"
    COL_Photo = IMG_Sablier
    // Lance la récupération de la photo dans une tâche parallèle
    MaTacheRechercheImage is ParallelTask = ParallelTaskExecute(RechercheImage, ...
    (COL_NumClient), ptoLightCopyHFSQLContext)
    // Lance l'affichage de l'image dans une tâche de continuation
    // qui interagit avec l'interface
    ParallelTaskExecuteAfter(MaTacheRechercheImage, AfficheImage, ...
    (COL_NumClient, ReturnedValuePreviousTask), ptoMainThread)
    END
  • Code of "FindImage" procedure: This process is used to retrieve the image.
    PROCÉDURE RechercheImage(LOCAL nIDClient is 8-byte int)
     
    // Récupération de la photo
    Résultat1 is boolean = HTTPRequest("http://Linkedin.com/photos/id=" + ID)
    IF Résultat1 = True THEN
    bufPhoto is Buffer = HTTPGetResult()
    bufPhoto = fLoadBuffer(fExeDir() + fSep() + "Photos\" + ID + ".jpg")
    END
     
    RETURN bufPhoto
  • Code of "DisplayImage" procedure: This procedure is used to display the image in the table.
    PROCÉDURE AfficheImage(nIDClient is 8-byte int, sCheminPhoto is string)
    // Recherche le client dans la table
    nIndice is int = TableSeek("FEN_MENU.TABLE_Client.COL_NumClient", nIDClient)
    IF nIndice > 0 THEN
    // Affiche la photo du client
    FEN_Menu.TABLE_Client.COL_Photo[nIndice] = sCheminPhoto
    END

Updating the GUI via a procedure run in the main thread

The controls of the window cannot be accessed from a parallel task. To display the image, the DisplayImage procedure is run by ExecuteMainThread. This function forces the procedure execution in the main thread.
You also have the ability to indicate to the DisplayImage procedure that it will always be run in the main thread. All you have to do is click the button in the bar of the code editor and check "Run in the main thread".
Code sample:
  • Code for displaying a table row:
    // Si la photo n'est pas encore renseignée
    IF COL_Photo ~= "" THEN
    // Positionne l'image de sablier en attendant de récupérer la photo depuis "Internet"
    COL_Photo  = IMG_Sablier
    // Lance la récupération de la photo dans une tâche parallèle
    MaTacheRechercheImage is ParallelTask = ParallelTaskExecute(RechercheImage, ...
    (COL_NumClient), ptoLightCopyHFSQLContext)
    END
  • Code of "FindImage" procedure: This process is used to retrieve the image.
    PROCÉDURE RechercheImage(LOCAL nIDClient is 8-byte int)
     
    // Récupération de la photo
    Résultat1 is boolean = HTTPRequest("http://Linkedin.com/photos/id=" + ID)
    IF Résultat1  = True THEN
    bufPhoto is Buffer = HTTPGetResult()
    bufPhoto = fLoadBuffer(fExeDir() + fSep() + "Photos\"+ ID + ".jpg")
    END
     
    // Appelle la procédure pour afficher l'image
    ExecuteMainThread(AfficheImage, nIDClient, bufPhoto)
  • Code of "DisplayImage" procedure: This procedure is used to display the image in the table.
    PROCÉDURE AfficheImage(nIDClient is 8-byte int, sCheminPhoto is string)
    // Recherche le client dans la table
    nIndice is int = TableSeek("FEN_MENU.TABLE_Client.COL_NumClient", nIDClient)
    IF nIndice > 0 THEN
    // Affiche la photo du client
    FEN_Menu.TABLE_Client.COL_Photo[nIndice] = sCheminPhoto
    END
Minimum version required
  • Version 20
This page is also available for…
Comments
Click [Add] to post a comment