Saltar al contenido principal
Versión: 21

Ejecución asíncrona

4D supports both synchronous and asynchronous execution modes, allowing developers to choose the best approach based on performance, responsiveness, and workload distribution.

Básicos

Ejecución sincrónica

Synchronous execution follows a sequential flow, a step-by-step where each instruction must complete before the next one starts. Esto significa que el hilo de ejecución se bloquea hasta que finaliza la operación.

Synchronous execution is used when:

  • La ejecución de las tareas debe seguir un orden estricto.
  • El impacto en el rendimiento es mínimo (por ejemplo, operaciones rápidas).
  • Se ejecuta en un contexto de un solo hilo donde el bloqueo es aceptable.
  • La ejecución síncrona bloquea la interfaz de usuario y es más adecuada para tareas rápidas y ordenadas en las que el bloqueo es aceptable.

Ejecución asíncrona

La ejecución asincrónica es event-driiven y permite que otras operaciones se completen. Se basa en callbacks, workers y event handlers para gestionar el flujo de ejecución.

La ejecución asíncrona se utiliza cuando:

  • Una operación tarda mucho tiempo (por ejemplo, esperando una respuesta del servidor).
  • La capacidad de respuesta es fundamental (por ejemplo, las interacciones de la interfaz de usuario).
  • Realización de tareas en segundo plano, comunicación en red o procesamiento paralelo.

Elegir entre ejecución síncrona y asíncrona:

ScenarioMejor enfoque
Operaciones rápidas con un procesamiento mínimoSíncrono
Tareas que requieren un orden de ejecución estrictoSíncrono
Tareas en segundo plano de larga duraciónAsynchronous
Long-running UI interactionsAsynchronous
Interacciones de interfaz de usuario de corta duraciónSíncrono
Cargas de trabajo multihilo de alto rendimientoAsynchronous

Principios básicos

4D ofrece capacidades integradas de ejecución asíncrona a través de varias clases y comandos. These allow background task execution, network communication, and large data processing, while waiting other operations to complete without blocking the current process.

The general concept of asynchronous event management in 4D is based on an asynchronous messaging model using workers (processes that listen to events) and callbacks (functions or formulas automatically invoked when an event occurs). Instead of waiting for a result (synchronous mode), you provide a function that will be automatically called when the desired event occurs. Las retrollamadas se pueden pasar como funciones clase (recomendado) o como objetos Formula.

This model is common to CALL WORKER, CALL FORM, and classes that support aynchronous execution. Todos estos comandos/clases inician una operación que se ejecuta en segundo plano. La sentencia que lanza la operación retorna inmediatamente, sin esperar a que la operación finalice.

Workers

Asynchronous programming relies on a system of workers (worker processes), which allows code to be executed in parallel without blocking the main process. This is particularly useful for long tasks (such as HTTP calls, executing external processes, background processing), while keeping the user interface responsive.

Using worker processes in asynchronous programming is mandatory since "classic" processes automatically terminate their execution when the process method ends, thus using callbacks is not possible. Un proceso worker permanece vivo y puede escuchar eventos.

Event queue (mailbox)

Cada worker (o ventana de formulario para CALL FORM) tiene su propia cola de mensajes. CALL WORKER or CALL FORM simply posts a message to this queue. El worker trata los mensajes uno a uno, en el orden en que llegan, dentro de su propio contexto. Se conservan las variables de proceso, las selecciones actuales, etc.

Comunicación bidireccional mediante mensajes

El proceso llamante envía un mensaje y el worker lo ejecuta. The worker can in turn post a message (via CALL WORKER or CALL FORM) back to the caller or another worker to notify an event (task completion, data received, error, progress, etc.). Este mecanismo sustituye al retorno clásico de las llamadas síncronas.

Event listening

In event-driven development, it is obvious that some code must be able to listen for incoming events. Events can be generated by the user interface (such as a mouse click on an object or a keyboard key pressed) or by any other interaction such as an http request or the end of another action. For example, when a form is displayed using the DIALOG command, user actions can trigger events that your code can process. Al hacer clic en un botón se activará el código asociado al botón.

In the context of asynchronous execution, the following features place your code in listening mode:

  • CALL WORKER ejecuta el código para el que ha sido llamado, luego vuelve a un estado de escucha desde donde puede ser llamado posteriormente.
  • CALL FORM abre un formulario y lo hace escuchar los mensajes entrantes de la cola de eventos.
  • a call for a wait() listens for terminate() or shutdown() in a callback from any other instance.

Event triggering

Los eventos se activan automáticamente durante el flujo de ejecución y se pasan a sus retrollamadas correspondientes. Se puede forzar la activación de eventos llamando a terminate() o shutdown() durante una wait().

Contexto de ejecución de retrollamada

When 4D execute one of your callbacks, it does so in the context of the current process (worker), i.e. if your object is instantiated inside a form, the callback function will be executed in the context of that same form.

For callbacks to work properly in fully asynchronous mode, the operation should generally be launched from a worker (via CALL WORKER). If launched from a process handling UI, some callbacks may not be called until the UI is listening events.

Releasing an asynchronous object

En 4D, todos los objetos son liberados cuando no existen más referencias a ellos en memoria. Esto suele ocurrir al final de la ejecución de un método para variables locales.

Para las clases asíncronas, 4D mantiene siempre una referencia adicional en el proceso que instanciaba el objeto. Esta referencia sólo se libera cuando finaliza la operación, es decir, después de que se active el evento onTerminate. Esta referencia automática permite a su objeto sobrevivir aunque no lo haya mencionado específicamente en una variable.

Si desea "forzar" la liberación de un objeto en cualquier momento, utilice un . hutdown() o función terminate(); desencadena el evento 'onTerminate` así libera el objeto.

Ejemplos que ilustran el concepto común

FeatureAsync LaunchCallback / Event Handling
CALL WORKERCALL WORKER("wk"; "MyMethod"; $params)MyMethod se llama con $params
CALL FORMCALL FORM($win; "MyMethod"; $params)MyMethod se llama con $params
4D.SystemWorker4D.SystemWorker.new(cmd; $options)Retrollamadas: onData, onResponse, onError, onTerminate

Programación asíncrona con clases 4D

Varias clases 4D soportan el procesamiento asíncrono:

  • HTTPRequest - Gestiona peticiones y respuestas HTTP asíncronas.
  • SystemWorker - Ejecuta procesos externos de forma asíncrona.
  • TCPConnection - Gestiona conexiones de cliente TCP con retrollamadas basadas en eventos.
  • TCPListener – Manages TCP server connections.
  • UDPSocket - Envía y recibe paquetes UDP.
  • WebSocket – Manages WebSocket client connections.
  • WebSocketServer - Gestiona las conexiones del servidor WebSocket.

Todas estas clases siguen las mismas reglas de ejecución asíncrona. Su constructor acepta un parámetro options que se usa para configurar su objeto asíncrono. It is recommended that the options object is a user class instance which has callback functions. Por ejemplo, puede crear una función onResponse() en la clase, que será llamada automáticamente de forma asíncrona cuando se dispare un evento reponse.

Recomendamos la siguiente secuencia:

  1. You create the user class where you declare callback functions, for example a cs.Params with onError() and onResponse() functions.
  2. Instanciará la clase usuario (en nuestro ejemplo utilizando cs.Params.new()) que configurará su objeto asíncrono.
  3. You call the constructor of the 4D class (for example 4D.SystemWorker.new()) and pass the options object as parameter. Inicia las operaciones pasadas inmediatamente sin demora.

Here is a full example of implementation of an options object based upon a user class:

// asynchronous code creation
var $options:=cs.Params.new(10) //see cs.Params class code below
var $systemworker:=4D.SystemWorker.new("/bin/ls -l /Users ";$options)


// "Params" class

Class constructor ($timeout : Real)
This.dataType:="text"
This.data:=""
This.dataError:=""
This.timeout:=$timeout

Function onResponse($systemWorker : Object)
This._createFile("onResponse"; $systemWorker.response)

Function onData($systemWorker : Object; $info : Object)
This.data+=$info.data
This._createFile("onData";this.data)

Function onDataError($systemWorker : Object; $info : Object)
This.dataError+=$info.data
This._createFile("onDataError";this.dataError)

Function onTerminate($systemWorker : Object)
var $textBody : Text
$textBody:="Response: "+$systemWorker.response
$textBody+="ResponseError: "+$systemWorker.responseError
This._createFile("onTerminate"; $textBody)

Function _createFile($title : Text; $textBody : Text)
TEXT TO DOCUMENT(Get 4D folder(Current resources folder)+$title+".txt"; $textBody)

Tenga en cuenta que onResponse, onData, onDataError y onTerminate son funciones soportadas por 4D.SystemWorker.

Once the user class is instantiated; 4D is put in event listening mode, in which case 4D can trigger an event that calls the corresponding function in the user class.

tip

En algunos casos, es posible que desee utilizar fórmulas como valores de propiedad en lugar de funciones de clase. Although it is not the best practice, a syntax such as the following is supported:

var $options.onResponse:=Formula(myMethod) 

Ejecución síncrona en código asíncrono

Incluso cuando se utiliza código moderno y asíncrono, puede ser necesario introducir cierto grado de ejecución síncrona. Por ejemplo, puede querer que una función espere un cierto tiempo para obtener un resultado. It could be the case with guaranteed fast network connections or system workers. A continuación, puede forzar la ejecución sincrónica utilizando la función wait().

The .wait() function pauses execution of the current process and puts 4D in event listening mode. Keep in mind that it will trigger events received from any sources, not only from the object on which the wait() function was called.

La función wait() retorna cuando el evento onTerminate ha sido disparado en el objeto, o cuando el tiempo de espera suministrado (si existe) ha expirado. Por consiguiente, puede salir explícitamente de un .wait() llamando a shutdown() o terminate() desde dentro de una retrollamda. En caso contrario, se sale de .wait() cuando finaliza la operación en curso.

Ejemplo:

var $options:=cs.Params.new() 
var $systemworker:=4D.SystemWorker.new("/bin/ls -l /Users ";$options)
$systemworker.wait(0.5) // Espera hasta 0.5 segundos para obtener información del archivo

Ver también

Blog: Lanzar un proceso externo de forma asíncrona
Llamada asíncrona