miércoles, 13 de agosto de 2014

Receta C# No. 4-12: Identificar Cuándo un Thread ha Finalizado su Ejecución

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Propiedad IsAlive
3.2 Método Join
4. Práctica: Código C#
5. Artefactos
6. Conclusiones
7. Glosario
8. Literatura & Enlaces

0. Introducción

En esta receta C# comprenderemos cómo identificar la completitud de la ejecución de un thread. Con esta habilidad que aprenderemos tanto conceptual como a nivel práctico, reconoceremos los dos métodos disponibles para esta tarea: uso de la propiedad Thread.IsAlive y el uso del método Join (también de la misma clase). Veremos cuál de estos resulta más eficiente o apropiado usando código fuente C#.

1. Problema

A medida que finaliza su ejecución un thread o un conjunto de threads, necesitamos realizar otras operaciones dependientes de su completitud; para esto requerimos conocer los detalles del proceso de identificación de cuándo un thread ha finalizado la ejecución de su proceso subyacente.

2. Solución

La clase Thread cuenta con dos elementos de programa (miembros) que resuelven el problema de identificación de completitud de la ejecución de un thread. Se trata de los siguientes miembros:
  • Propiedad Thread.IsAlive, y 
  • el método sobrecargado Join.

3. Discusión de la Solución

Comencemos por detallar el uso de los elementos de solución identificados en la sección 2.

3.1 Propiedad IsAlive

Con la propiedad IsAlive [2] (System.Threading.Thread) podemos obtener un valor lógico (o booleano) que indica el estado de ejecución de un thread. Esta es su firma:

public bool IsAlive { get; }

Descripción puntual:
  • Valor de propiedad:
    • Tipo System.Boolean: true si el thread se haya en ejecución; en caso contrario, false.
A pesar de su utilidad para conocer la actividad de ejecución de un thread, el uso de esta propiedad resulta ineficiente debido a que se tiene que recurrir a una construcción iteración while o  for, la cual que generará varios ciclos o tiempo de procesador hasta que se complete la ejecución del thread en cuestión. Comprendamos esto a través de un ejemplo:

Notemos con especial cuidado la línea 19: aquí realizamos comprobaciones constantes obteniendo el valor dela propiedad IsAlive del thread (t) que se haya en ejecución. Pueden ocurrir un sinnúmero de comprobaciones y esto recae en uso ineficiente de tiempo de procesador.

Compilación:


  1. csc /target:exe UsoIsAlive.cs

Ejecución assembly:


  1. .\UsoIsAlive.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local).
Ejecución assembly UsoIsAlive.exe
Figura 1. Ejecución assembly UsoIsAlive.exe.

3.2 Método Join

El método Join cuenta con las siguientes versiones sobrecargadas [3]:
Versiones sobrecargadas del método Thread.Join
Figura 2. Versiones sobrecargadas del método Thread.Join.
La primera versión con firma [4]:

public void Join()

Sencillamente bloquea el thread donde se realiza la llamada y espera a que finaliza su ejecución.

Mientras que con las firmas [5] y [6]:

public bool Join(int millisecondsTimeout)

public bool Join(TimeSpan timeout)

podemos obtener un valor lógico que indica si el thread aún se haya en ejecución. Los argumentos -tipos int y TimeSpan- especifican un tiempo de espera medido en milsegundos y en un intervalo de tiempo; transcurrido este tiempo se comprueba si el thread ya finalizado. Procedamos a elaborar un ejemplo para comprender su verdadera utilidad con la primera versión:

En la línea 17 se invoca el método Join y se espera a el proceso subyacente (Tarea) haya completado su ejecución, mientras tanto Main permanecerá en espera. Evidentemente, esto resulta más eficiente en cuanto al uso de recursos del procesador respecto a la versión de ejemplo con IsAlive de la sección 3.1.

Compilación:


  1. csc /target:exe UsoJoin.cs

Ejecución assembly:


  1. .\UsoJoin.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local).
Ejecución assembly UsoJoin.exe
Figura 3. Ejecución assembly UsoJoin.exe.

4. Práctica: Código C#

Veamos este último ejemplo adaptado de [1] para afianzar el conocimiento de la sección anterior.

En la línea 21 comprobamos si el thread t ha finalizado su ejecución a través de la invocación de Join. Especificamos un tiempo de espera de 2 segundos. Debido a que el tiempo de ejecución (simulado) del método MostrarMensaje es superior a este tiempo, en pantalla se mostrará el mensaje anidado en ifDespués, línea 29, mostramos en pantalla el estado de ejecución del thread consultando la propiedad IsAlive. Bloqueamos nuevamente el thread Main en la línea 32 a través de una invocación a Join. Al finalizar la ejecución MostrarMensaje, insistimos en consultar el estado de ejecución de t en la línea 35.

Compilación:


  1. csc /target:exe FinalizacionEjecucionThread.cs

Ejecución assembly:


  1. .\FinalizacionEjecucionThread.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local).
Ejecución assembly FinalizacionEjecucionThread.exe
Figura 4. Ejecución assembly FinalizacionEjecucionThread.exe.

5. Artefactos

Enlaces de descarga de los artefactos producidos en el desarrollo de esta receta C#:

6. Conclusiones

Comprendimos a través del uso de la propiedad IsAlive y las versiones sobrecargadas del método Join a identificar cuándo un thread ha finalizado su ejecución. Preferimos el uso (en general) de Join debido a su uso eficiente de recursos, en particular, de ciclos del procesador. En la próxima receta entraremos a practicar sobre el proceso de terminación de la ejecución arbitraria de un thread.

7. Glosario

  • Eficiencia
  • Ejecución
  • Método
  • Propiedad
  • Recurso de máquina
  • Thread
  • Tiempo de procesador

8. Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: Thread.IsAlive Property (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.thread.isalive%28v=vs.110%29.aspx
[3]: Thread.Join Method (System.Threading) - http://msdn.microsoft.com/en-us/library/System.Threading.Thread.Join%28v=vs.110%29.aspx
[4]: Thread.Join Method (System.Threading) - http://msdn.microsoft.com/en-us/library/95hbf2ta(v=vs.110).aspx
[5]: Thread.Join Method (Int32) (System.Threading) - http://msdn.microsoft.com/en-us/library/6b1kkss0(v=vs.110).aspx
[6]: Thread.Join Method (TimeSpan) (System.Threading) - http://msdn.microsoft.com/en-us/library/23f7b1ct(v=vs.110).aspx


M

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.