Saltar al contenido principal
Versión: Siguiente

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:

  • Task execution must follow a strict order.
  • Performance impact is minimal (e.g., quick operations).
  • 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).
  • Responsiveness is critical (e.g., UI interactions).
  • 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
High-performance, multi-threaded workloadsAsynchronous

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. Callbacks can be passed as class functions (recommended) or Formula objects.

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. The statement that launches the operation returns immediately, without waiting for the operation to finish.

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. A worker process stays alive and can listen to events.

Event queue (mailbox)

Each worker (or form window for CALL FORM) has its own message queue. CALL WORKER o CALL FORM simplemente envía un mensaje a esta cola. El worker trata los mensajes uno a uno, en el orden en que llegan, dentro de su propio contexto. Process variables, current selections, etc. are preserved.

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. This reference is only released when the operation is finished, i.e. after the onTerminate event is triggered. 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)Callbacks: onData, onResponse, onError, onTerminate

Programación asíncrona con clases 4D

Several 4D classes support asynchronous processing:

  • 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. It starts the operations passed immediately without delay.

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) 

Synchronous execution in asynchronous code

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