El lado oscuro de Application.ProcessMessages en aplicaciones de Delphi

Artículo presentado por Marcus Junglas

Al programar un controlador de eventos en Delphi (como el Al hacer clic evento de un TButton), llega el momento en que su aplicación necesita estar ocupada por un tiempo, p. el código necesita escribir un archivo grande o comprimir algunos datos.

Si haces eso, notarás que su aplicación parece estar bloqueada. Su formulario ya no se puede mover y los botones no muestran signos de vida. Parece estar estrellado.

La razón es que una aplicación Delpi es de un solo subproceso. El código que está escribiendo representa solo un conjunto de procedimientos que son llamados por el hilo principal de Delphi cada vez que ocurre un evento. El resto del tiempo, el hilo principal maneja los mensajes del sistema y otras cosas como las funciones de manejo de formularios y componentes..

Por lo tanto, si no termina el manejo de su evento haciendo un trabajo largo, evitará que la aplicación maneje esos mensajes.

Una solución común para este tipo de problemas es llamar a "Application.ProcessMessages". "Aplicación" es un objeto global de la clase TApplication.

Application.Processmessages maneja todos los mensajes en espera, como movimientos de ventanas, clics de botones, etc. Se usa comúnmente como una solución simple para mantener su aplicación "funcionando".

Lamentablemente, el mecanismo detrás de "ProcessMessages" tiene sus propias características, lo que puede causar una gran confusión!

Qué hace ProcessMessages?

PprocessMessages maneja todos los mensajes del sistema en espera en la cola de mensajes de las aplicaciones. Windows usa mensajes para "hablar" con todas las aplicaciones en ejecución. La interacción del usuario se lleva al formulario a través de mensajes y "ProcessMessages" los maneja.

Si el mouse se cae en un TButton, por ejemplo, ProgressMessages hace todo lo que debe suceder en este evento, como volver a pintar el botón a un estado "presionado" y, por supuesto, una llamada al procedimiento de manejo de OnClick () si uno asignado.

Ese es el problema: cualquier llamada a ProcessMessages podría contener una llamada recursiva a cualquier controlador de eventos nuevamente. Aquí hay un ejemplo:

Utilice el siguiente código para el controlador uniforme de OnClick de un botón ("trabajo"). La declaración for simula un trabajo de procesamiento largo con algunas llamadas a ProcessMessages de vez en cuando.

Esto se simplifica para una mejor legibilidad:

 en MyForm:
  Nivel de trabajo: entero;
OnCreate:
  Nivel de trabajo: = 0;
procedimiento TForm1.WorkBtnClick (Remitente: TObject);
var
  ciclo: entero;
empezar
  inc (nivel de trabajo);
  para ciclo: = 1 a 5 5 hacer
  empezar
    Memo1.Lines.Add ('- Work' + IntToStr (WorkLevel) + ', Cycle' + IntToStr (cycle);
    Application.ProcessMessages;
    dormir (1000); // o algún otro trabajo
  final;
  Memo1.Lines.Add ('Work' + IntToStr (WorkLevel) + 'finalizado');
  dec (Nivel de trabajo);
final;

SIN "ProcessMessages", las siguientes líneas se escriben en la nota, si se presionó el botón DOS VECES en poco tiempo:

 - Trabajo 1, ciclo 1
- Trabajo 1, ciclo 2
- Trabajo 1, ciclo 3
- Trabajo 1, ciclo 4
- Trabajo 1, ciclo 5
Trabajo 1 terminado.
- Trabajo 1, ciclo 1
- Trabajo 1, ciclo 2
- Trabajo 1, ciclo 3
- Trabajo 1, ciclo 4
- Trabajo 1, ciclo 5
Trabajo 1 terminado.