|
|
|
|
|
- Overview
- Principle
- How to?
- 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
- Manipulating the controls from a parallel task
- Example: Accelerating the processes
- Speed up processing: calculate statistics
- 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
The computers are becoming more and more powerful. The computers have powerful processors with several cores. To improve the performance 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: - accelerate application processing times thanks to parallelism Parallelism: several processes are run in parallel instead of sequentially: application speed is improved.
A simple example Calculate the number of emails sent and received for each email address in 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 application responsiveness Line: several long, blocking processes are run in parallel instead of sequentially, so the user doesn't have the impression of being blocked.
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.
To manage the parallel tasks, WLanguage proposes: - a variable of type ParallelTask. 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*).
Note: It is also possible to use the Description of ParallelTask variable type. This type of variable can only be used to describe a parallel task. Once the parallel task is defined, its characteristics cannot be modified. Principle To implement a management of parallel tasks, you must: - Create and run a parallel task.
- Wait for the execution of the task and retrieve the return value.
- Manage (if necessary) the sequence of parallel tasks.
- Manipulate (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:
// Declares a variable to handle a parallel task t is ParallelTask // Run and describe the parallel task t = ParallelTaskExecute(Proc, ("First parameter", 2))
- Declaration and description of the parallel task. Then, the parallel task is run by ParallelTaskExecute.
t is ParallelTask(Proc, ("First parameter", 2))
ParallelTaskExecute(t)
Note: When describing the parallel task, you can specify: - the procedure to run.
- the parameters expected by the procedure.
- parallel task execution mode: 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 name | Type used | Effect |
---|
Canceled | Boolean | - True if the task is canceled,
- False otherwise.
This property is read-only. | Completed | Boolean | - True if the task is completed,
- False otherwise.
This property is read-only. | Novedad versión 2025Extra | Variant | Permite almacenar información avanzada sin afectar la ejecución de la aplicación. Puede almacenar valores de cualquier tipo (array, etc.). También es posible agregar miembros a la propiedad Extra. Ejemplo:
MyVariable.Extra.Info1 = Value MyVariable.Extra[Info2] = Value2 MyVariable.Extra.Date = DateSys() | Identifier | Integer | Task identifier. This identifier can be used for debugging purpose for example. This property is read-only. | ReturnedValue | Value 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 read-only. | Status | Integer constant | Status of the task: - tpeCancelled: parallel job is cancelled (function ParallelTaskCancel).
- tpeRequestedCancellation: a cancellation request has been made on the parallel task (function ParallelTaskRequestCancellation)..
- tpeWaitExecution the parallel task is waiting to be executed.
- tpePreviousPreviousTask the parallel task waits for the execution of a previous parallel task.
- tpeExecutionInProgress the parallel task is currently running.
- tpeNotScheduled: parallel task is not scheduled.
- tpeTerminated: parallel task completed.
This property is 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: The ValeurRenvoyée property of the ParallelTask variable gets the value returned by the procedure executed by the parallel task. Warning: This value is only available if the parallel task has been completed. 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. Parallel task chaining can be defined: a task can wait for one or more tasks to finish before executing itself. The following functions are used to define a continuation task: | | ParallelTaskExecuteAfter | Indicates a continuation parallel task that will be run when one of the specified parallel task is completed. | ParallelTaskExecuteAfterAll | Indica una tarea paralela de continuación que se ejecutará cuando todas las tareas de un array de tareas paralelas hayan finalizado. | ParallelTaskExecuteAfterOne | Indica una tarea paralela de continuación que se ejecutará una vez finalizada la primera tarea de un array de tareas paralelas. |
Note: In a continuation task, it is possible to: Manipulating 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. Note: It is also possible to use the ExecuteMainThread function to execute a specific display procedure from the parallel task. Example: Accelerating the processes Speed up processing: calculate statistics An application uses 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 as 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):
nAddressesInError is int
HourGlass(True)
ChronoStart()
FOR EACH Customer
IF CalculateStatEmailAddress(Customer.Email, 1) = False THEN
nAddressesInError++
END
END
HourGlass(False)
LIB_Résultat_1 = StringBuild("Result: %1 addresses in error", nAdressesInError)
Info("Process completed", DurationToString(ChronoEnd(), "MMm SSs CCC"))
- Code using parallel tasks:
nAddressesInError is int
arrTasks is array of ParallelTask
ATask is ParallelTask
HourGlass(True)
ChronoStart()
FOR EACH Customer
ATask = ParallelTaskExecute(CalculateStatEmailAddress, ...
(Customer.Email, 1), ptoLightCopyHFSQLContext)
Add(arrTasks, ATask)
END
ParallelTaskWaitAll(arrTasks)
HourGlass(False)
FOR EACH ATask OF arrTasks
IF ATask..ReturnedValue = False THEN
nAddressesInError++
END
END
LIB_Résultat_2 = StringBuild("Result: %1 addresses in error", nAdressesInError)
Info("Process completed", 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.
For this example, here are two different codes: these two codes present two different ways of updating the HMI: 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:
// If the photo is not filled yet IF COL_Photo ~= "" THEN // Positions the hourglass image while waiting for the photo to be retrieved from "Internet" COL_Photo = IMG_Hourglass // Starts retrieving the photo in a parallel task MyTaskFindImage is ParallelTask = ParallelTaskExecute(FindImage, ... (COL_CustomerNum), ptoLightCopyHFSQLContext) // Starts displaying the image in a continuation task // that interacts with the interface ParallelTaskExecuteAfter(MyTaskFindImage, DisplayImage, ... (COL_CustomerNum, ReturnedValuePreviousTask), ptoMainThread) END
- Procedure code "SearchImage": This procedure retrieves the image.
PROCEDURE FindImage(LOCAL nCustomerID is 8-byte int)
Result1 is boolean = HTTPRequest("http://Linkedin.com/photos/id=" + ID)
IF Result1 = True THEN
bufPhoto is Buffer = HTTPGetResult()
bufPhoto = fLoadBuffer(fExeDir() + fSep() + "Photos\" + ID + ".jpg")
END
RETURN bufPhoto
- Code for "DisplayImage" procedure: This procedure displays the image in the.
PROCEDURE DisplayImage(nCustomerID is 8-byte int, sPhotoPath is string) // Finds the customer in the table nIndex is int = TableSearch("WIN_MENU.TABLE_Customer.COL_CustomerNum", nCustomerID) IF nIndex > 0 THEN // Displays the customer photo WIN_Menu.TABLE_Customer.COL_Photo[nIndex] = sPhotoPath 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:
// If the photo is not filled yet IF COL_Photo ~= "" THEN // Positions the hourglass image while waiting for the photo to be retrieved from "Internet" COL_Photo = IMG_Hourglass // Starts retrieving the photo in a parallel task MyTaskFindImage is ParallelTask = ParallelTaskExecute(FindImage, ... (COL_CustomerNum), ptoLightCopyHFSQLContext) END
- Procedure code "SearchImage": This procedure retrieves the image.
PROCÉDURE FindImage(LOCAL nCustomerID is 8-byte int)
// Retrieve the photo Result1 is boolean = HTTPRequest("http://Linkedin.com/photos/id=" + ID) IF Result1 = True THEN bufPhoto is Buffer = HTTPGetResult() bufPhoto = fLoadBuffer(fExeDir() + fSep() + "Photos\"+ ID + ".jpg") END
// Calls the procedure to display the image ExecuteMainThread(DisplayImage, nCustomerID, bufPhoto)
- Code for "DisplayImage" procedure: This procedure displays the image in the.
PROCEDURE DisplayImage(nCustomerID is 8-byte int, sPhotoPath is string) // Finds the customer in the table nIndex is int = TableSearch("WIN_MENU.TABLE_Customer.COL_CustomerNum", nCustomerID) IF nIndex > 0 THEN // Displays the customer photo WIN_Menu.TABLE_Customer.COL_Photo[nIndex] = sPhotoPath END
Esta página también está disponible para…
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|