|
|
|
|
- Presentación
- Principio
- ¿Cómo proceder?
- Principio
- Crear y ejecutar una tarea paralela
- La palabra clave de MyParallelTask
- Esperar la ejecución de la tarea y recuperar el valor de retorno
- Gestión de la secuencia de tareas paralelas
- Manejo de los controles desde una tarea paralela
- Ejemplo: Acelerar los procesos
- Acelerar los procesos: cálculo estadístico
- Ejemplo: Mejorar la reactividad de la aplicación
- Mejorar la reactividad de la aplicación
- Actualización de la GUI mediante una tarea de continuación
- Actualizando el GUI a través de una corrida de Procedure en el Thread principal
Gestión de tareas paralelas
Los ordenadores son cada vez más potentes. Los ordenadores tienen potentes procesadores con varios núcleos. Para mejorar el rendimiento de las aplicaciones y trabajar con el máximo número de núcleos del ordenador, ahora tiene la posibilidad de dividir los procesos en una lista de subprocesos (llamados tareas) y ejecutarlos en paralelo en lugar de secuencialmente. Una tarea es una Procedure a ejecutar que puede esperar parámetros y que puede devolver un resultado. Estas tareas serán ejecutadas por el equipo en uno o más hilos según la disponibilidad de el equipo. Una tarea puede dividirse en varias subtareas. ¿Cuál es el beneficio de las tareas paralelas? Las tareas paralelas son useful a: - acelera el tiempo de aplicación de Process mediante el paralelismo: varios procesos se ejecutan en paralelo en lugar de ejecutarse secuencialmente: se mejora la velocidad de la aplicación.
Un ejemplo sencillo: iniciar un cálculo estadístico para enviar y recibir correos electrónicos en cada correo electrónico Address de la base de datos. Si el cálculo estadístico de un correo electrónico Address toma un segundo y si la base de datos contiene 200 000 correos electrónicos Address es, el cálculo toma más de dos días. Para ir más rápido, tienes la capacidad de iniciar una tarea paralela por cada correo electrónico que Address encontró. Este ejemplo se presenta en Ejemplo: Acelerar los procesos. - mejorar la reactividad de la aplicación: varios procesos largos y de bloqueo se ejecutan en paralelo en lugar de ejecutarse secuencialmente: el usuario no se siente atrapado.
Un ejemplo sencillo: Un control Tabla muestra una lista de contactos cuya foto se carga desde un INTERNET Address. Para cada contacto, la aplicación realiza una solicitud de INTERNET (que desencadena una desaceleración). Para que el control Tabla se llene sin ser bloqueado, el proceso de visualización de fila inicia una tarea paralela que se usa para iniciar la solicitud de INTERNET y para actualización la GUI si es necesario. Este ejemplo se presenta en Ejemplo: Mejorar la reactividad de la aplicación.
Para gestionar las tareas paralelas, WLanguage propone: - una variable de tipo ParallelTask. Este tipo de Variable se utiliza para manipular una tarea paralela. Este tipo de Variable no puede ser usado para modificar las características de una tarea paralela.
- funciones de gestión de tareas (ParallelTask*).
Observación: También tiene la posibilidad de utilizar el Descripción de ParallelTask Variable. Este tipo de Variable sólo puede ser usado para describir una tarea paralela. Una vez definida la tarea paralela, sus características no pueden modificarse. Principio Para implementar una gestión de tareas paralelas, debe: - Crear y ejecutar una tarea paralela.
- Esperar la ejecución de la tarea y recuperar el valor de retorno.
- Gestionar (si es necesario) la secuencia de tareas paralelas.
- Manejar (si es necesario) los controles de una tarea paralela..
Crear y ejecutar una tarea paralela Una tarea paralela debe estar asociada a una ParallelTask Variable. Se pueden utilizar varios métodos para declarar un ParallelTask Variable: - Declaración simple. La tarea paralela se describe durante su ejecución con ParallelTaskExecute:
// Declares a variable to handle a parallel task t is ParallelTask // Run and describe the parallel task t = ParallelTaskExecute(Proc, ("First parameter", 2))
- Declaración y description de la tarea paralela. A continuación, la tarea paralela es ejecutada por ParallelTaskExecute.
// Builds a parallel task t is ParallelTask(Proc, ("First parameter", 2)) // Triggers the execution of parallel task ParallelTaskExecute(t)
Observación: Al describir la tarea paralela, tiene la capacidad de especificar: - el Procedure para dirigir.
- los parámetros esperados por la Procedure.
- el modo de tiempo de ejecución de la tarea paralela: gestión de los contextos HFSQL e interacciones con el principal Thread.
La palabra clave de MyParallelTask MyParallelTask se utiliza para gestionar la tarea paralela actual y descubrir sus propiedades. Esto le permite acceder a la información sobre la tarea paralela actual en el código ejecutado por una tarea paralela. Las propiedades accesibles son las de las variables de ParallelTask:
| | | Nombre de la propiedad | Tipo utilizado | Efecto |
---|
Cancelado | booleano | - True si se cancela la tarea,
- False en caso contrario.
Esta propiedad es de solo lectura. | Concluido | booleano | - True si se completó la tarea,
- False en caso contrario.
Esta propiedad es de solo lectura. | Estado | Constante de tipo Integer | Status de la tarea: - ptsCanceled: la tarea paralela se cancela (ParallelTaskCancel).
- ptsCancellationRequested: se ha realizado una solicitud de cancelación en la tarea paralela (ParallelTaskRequestCancellation).
- ptsWaitingExecution: la tarea paralela está a la espera de ser ejecutada.
- ptsWaitingPrevious: La tarea paralela espera la ejecución de una tarea paralela anterior..
- ptsExecutionInProgress: la tarea paralela se está ejecutando actualmente.
- ptsNotScheduled: la tarea paralela no está programada.
- ptsCompleted: la tarea paralela ha terminado.
Esta propiedad es de solo lectura. | Identificador | Integro | Identificador de tareas. Este identificador puede ser usado para propósitos de depuración, por ejemplo. Esta propiedad es de solo lectura. | ReturnedValue | Valor devuelto por la tarea. | Atención: - Si la tarea aún está en curso, la ReturnedValue Property espera el final de la tarea
- Si la tarea se completa sin error fatal, la Property devuelve los valores de retorno de la Procedure de la tarea.
Esta propiedad es de solo lectura. |
Esperar la ejecución de la tarea y recuperar el valor de retorno Se pueden iniciar varias tareas paralelas al mismo tiempo. Tienes la capacidad de esperar la ejecución de una o más tareas paralelas antes de ejecutar un Process: La propiedad ValeurRenvoyée de la variable ParallelTask obtiene el valor devuelto por el Procedure ejecutado por la tarea paralela. Atención: Este valor sólo está disponible si la tarea paralela ha finalizado.. Si la tarea está en progreso, la llamada a este Property se bloquea hasta el final de la tarea. Gestión de la secuencia de tareas paralelas Se pueden iniciar varias tareas paralelas al mismo tiempo. Tiene la capacidad de definir la secuencia de tareas paralelas: una tarea puede esperar al final de la ejecución de una o más tareas antes de ejecutarse. Las siguientes funciones se utilizan para definir una tarea de continuación: | | ParallelTaskExecuteAfter | Indica una tarea paralela de continuación que se ejecutará cuando finalice una de las tareas paralelas especificadas. | 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. |
Observación: En una tarea de continuación, puede: Manejo de los controles desde una tarea paralela No puede actuar en la interfase desde una tarea paralela. Por lo tanto, no puedes asignar un control, llenar una tabla o control Looper. Sólo una tarea definida por la constante ptoMainThread puede ser ejecutada en el Thread principal y puede actualizar los controles si es necesario. Observación: También puede utilizar ExecuteMainThread para ejecutar una visualización específica Procedure desde la tarea paralela. Ejemplo: Acelerar los procesos Acelerar los procesos: cálculo estadístico Una aplicación utiliza el procedimiento CalculateStatEmailAddress para realizar cálculos estadísticos sobre las operaciones de envío y recepción de cada dirección de correo electrónico del archivo CUSTOMER. Este Procedure toma como parámetro el correo electrónico Address y calcula todas las estadísticas de este Address. Si el cálculo estadístico en un correo electrónico Address toma un segundo y si la base de datos contiene 200 000 correos electrónicos Address es, el cálculo toma más de dos días (200 000 segundos). Para ir más rápido, tienes la capacidad de iniciar una tarea paralela por cada correo electrónico que Address encontró. Ejemplo de código: - Código inicial (antes de utilizar tareas paralelas):
nAddressesInError is int HourGlass(True) ChronoStart() // Browses the list of customers FOR EACH Customer // Starts the statistical calculation on the email address IF CalculateStatEmailAddress(Customer.Email, 1) = False THEN nAddressesInError++ END END HourGlass(False) STC_Result_1 = StringBuild("Result: %1 addresses in error", nAddressesInError) Info("Process completed", DurationToString(ChronoEnd(), "MMm SSs CCC"))
- Code thai está usando las tareas paralelas:
nAddressesInError is int arrTasks is array of ParallelTasks ATask is ParallelTask HourGlass(True) ChronoStart() // Browses the list of customers FOR EACH Customer // Starts the statistical calculation on the email address via a parallel task ATask = ParallelTaskExecute(CalculateStatEmailAddress, ... (Customer.Email, 1), ptoLightCopyHFSQLContext) // Stores this task in an array Add(arrTasks, ATask) END // Waits for the end of task execution ParallelTaskWaitAll(arrTasks) HourGlass(False) // Browses the tasks FOR EACH ATask OF arrTasks IF ATask..ReturnedValue = False THEN nAddressesInError++ END END STC_Result_2 = StringBuild("Result: %1 addresses in error", nAddressesInError) Info("Process completed", DurationToString(ChronoEnd(), "MMm SSs CCC"))
Ejemplo: Mejorar la reactividad de la aplicación Mejorar la reactividad de la aplicación Un control Tabla muestra una lista de contactos cuya foto se carga desde un INTERNET Address. Para cada contacto, la aplicación realiza una solicitud de INTERNET (que desencadena una desaceleración). Para mejorar la reactividad de la aplicación y obtener una interfaz gráfica de usuario fluida, se inicia una tarea paralela en el Process para mostrar un fila de control Tabla. Esta tarea paralela: - recibe el identificador de Contact en el prameter.
- realiza la solicitud de INTERNET a get el Image.
- recupera el Image.
- llama una función para actualizar el control Tabla.
Veamos dos códigos diferentes para este ejemplo: estos dos códigos presentan dos métodos diferentes para actualizar la GUI: Actualización de la GUI mediante una tarea de continuación Al no ser posible la actualización de la interfaz desde una tarea paralela ejecutada en el Thread principal, se implementa una tarea de continuación específica para la visualización mediante ParallelTaskExecuteAfter. Uno de los parámetros pasados a la tarea de continuación corresponde al valor devuelto por la tarea paralela principal.. Para especificar este parámetro, todo lo que tiene que hacer es utilizar la función ReturnedValuePreviousTask descriptor. Ejemplo de código: - Código para mostrar un tabla fila:
// 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
- Código de "FindImage" Procedure: Este Process se usa para recuperar el 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
RESULT bufPhoto
- Código de "DisplayImage" Procedure: Este Procedure se usa para mostrar el Image en el tabla.
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
Actualizando el GUI a través de una corrida de Procedure en el Thread principal No se puede acceder a los controles de la ventana desde una tarea paralela. Para mostrar la imagen, el programa DisplayImage Procedure es ejecutado por ExecuteMainThread. Esta función obliga a la ejecución de la Procedure en la thread principal. También tienes la capacidad de indicar al DisplayImage Procedure que siempre se ejecutará en el Thread principal. Lo único que tienes que hacer es pulsar el botón en la barra del editor de código y marcar "Ejecutar en el Thread principal". Ejemplo de código: - Código para mostrar un tabla fila:
// 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
- Código de "FindImage" Procedure: Este Process se usa para recuperar el 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)
- Código de "DisplayImage" Procedure: Este Procedure se usa para mostrar el Image en el tabla.
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…
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|