Capitulo 4. Destrucción simple de hilos.

En este capítulo

Consideraciones de completado, terminación y destrucción de hilos.

En el capitulo 2 se dio un lineamiento de algunos de los problemas relacionado con la finalización de hilos. Hay dos consideraciones principales:

Estos puntos están fuertemente relacionados. Si un hilo no tiene que comunicar nada al hilo principal de la VCL cuando haya terminado, o si uno usa la técnica descripta en el capítulo anterior para comunicar los resultados justo antes de que el hilo termine, entonces no hay necesidad del hilo principal de VCL de participar en ninguna limpieza del hilo. En este caso, uno puede establecer a verdadero la variable FreeOnTerminate del hilo, y dejar que el hilo se encargue de liberarse a sí mismo. Recuerda que si uno hace esto, el usuario puede forzar la salida del programa, resultando en una terminación de todos los hilos en él, con posibles consecuencias indeseables. Si el hilo sólo escribe en la memoria, o se comunica con otras partes de la aplicación, entonces este no es un problema, pero si escribe en un archivo o en un recurso compartido del sistema, entonces esto es inaceptable.

Si un hilo tiene que intercambiar información con la VCL antes de terminar, entonces un mecanismo tiene que ser encontrado para sincronizar el hilo principal de VCL con el hilo en funcionamiento, y el hilo principal de VCL debe realizar la limpieza (tu tienes que escribir el código para liberar el hilo). Dos mecanismos serán presentados luego.

Hay un punto más para tener en cuenta:

Esto puede suceder bastante seguido. Algunos hilos, especialmente aquellos que procesan E/S, se ejecutan en un bucle permanente: el programa puede estar recibiendo siempre más datos, y el hilo siempre tiene que estar preparado para procesarlos hasta que el programa termine.

Entonces, si organizamos estos puntos en orden inverso…

Terminado prematuro de hilos.

En algunas circunstancias, un hilo puede necesitar indicarle a otro hilo que debe terminar. Esto generalmente ocurre si el hilo está ejecutando una operación muy larga, y el usuario decide salir de la aplicación, o la operación debe ser abortada. TThread provee un mecanismo simple para soportar esto en la forma del método Terminate, y la propiedad Terminated. Cuando un hilo es creado su propiedad terminated se establece a false. Cuando se llama al método terminate de un hilo, la propiedad terminated para ese hilo es ahora true. Es la responsabilidad de todos los hilos de verificar periódicamente si se les ha solicitado terminar, y si así fuera, salir limpiamente. Nótese que no se producen sincronizaciones de gran escala en este proceso; cuando un hilo activa la propiedad terminated del otro, no puede asumir que el otro hilo ha leído el valor de la propiedad terminated y comenzó su finalización. La propiedad Terminated es simplemente una señal, diciendo “por favor termina tan rápido como sea posible”. El diagrama de abajo ilustra esta situación.


Cuando se diseñan los objetos hilos, se deberá considerar leer la variable terminated cuando sea necesario. Si el hilo se bloquea, como resultado de algún mecanismo de sincronización de los que discutiremos luego, podría tener que sobrecargar el método terminate para desbloquear el hilo. En particular, recodará llamar primero al método heredado (inherited) terminate, antes de desbloquear el hilo, si espera que su próxima verificación de terminated devuelva verdadero. Pronto veremos más de esto. Como ejemplo, aquí hay una pequeña modificación al hilo que calcula los números primos del capitulo anterior, para asegurarnos de que verifica el valor de terminated. He asumido que es aceptable para el hilo devolver un resultado incorrecto cuando se establece la propiedad terminated.

El evento OnTerminate.

El evento OnTerminate ocurre cuando un hilo realmente ha terminado su ejecución. No ocurre cuando es llamado el método terminate. Este evento es bastante útil, en el sentido de que se ejecuta en el contexto del hilo principal de VCL, de la misma forma en que lo hacen los métodos pasados a synchronize. Además, si uno desea ejecutar algunas operaciones de la VCL con un hilo que se libera automáticamente a sí mismo, entonces este es el lugar de hacerlo. La mayoría de los nuevos programadores de hilos de ejecución van a encontrar esto como la mejor manera de lograr que un hilo no-VCL transfiera sus datos de vuelta al VCL, con un mínimo de alboroto, y sin requerir llamadas explícitas a synchronize.


Como pueden ver en el diagrama de arriba, OnTerminate trabaja bastante parecido a como lo hace Synchronize, y es prácticamente idéntico semánticamente a poner una llamada a Synchronize al final del hilo. El principal uso de esto es que, mediante el uso de indicadores, como  “La aplicación puede finalizar” o conteos de referencias de los hilos que hay en funcionamiento en el hilo principal de VCL, un mecanismo simple puede ser provisto para asegurarse de que el hilo principal de VCL puede salir sólo cuando todos los demás hilos han terminado. Aquí hay algunos detalles de sincronización involucrados, especialmente si un programador va a poner una llamada a Application.Terminate en el evento OnTerminate de un hilo, pero todo esto será tratado más tarde.

Terminación controlada de hilos – Efoque 1.

En este ejemplo, tomaremos el código del programa de números primos del capítulo 3 y lo modificaremos de modo que el usuario no pueda cerrar la aplicación cuando hay otros hilos ejecutándose. Esto se vuelve simple. De hecho, no necesitamos modificar el código del hilo ni en lo más mínimo. Nosotros simplemente agregaremos una referencia a un campo de conteo en el hilo principal, incrementándolo cuando se cree un nuevo hilo, estableciendo el evento OnTerminate del hilo para que apunte a un manejador en el formulario principal que decremente el conteo de referencia, y cuando el usuario solicite terminar la aplicación, mostraremos una caja de diálogo de alerta si fuera necesario.

El ejemplo muestra lo simple de este enfoque: todo el código concerniente con tomar cuenta de los números de hilos en ejecución sucede en el hilo principal de VCL, y el código es esencialmente disparado por un evento, lo mismo que como sería con cualquier otra aplicación Delphi. En el próximo capitulo, vamos a considerar un enfoque sensiblemente más complicado, que es beneficioso cuando se usan mecanismos de sincronización más avanzados.


Contenido - Anterior - Siguiente