miércoles, 18 de junio de 2014

Receta Multithreading No. 1-2 en C#: Pausar un Thread

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Método Sleep(int)
3.2 Método Sleep(TimeSpan)
3.3 Ejemplos
3.3.1 Uso básico de Sleep(int)
3.3.2 Pausar dos threads
3.3.3 Precisión con Thread.Sleep
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

Doy inicio a esta nueva receta de multithreading en C#. En esta oportunidad vamos a concentrarnos en un tema bastante importante e interesante que tiene que ver con la detención temporal o pausa de un thread que se encuentre en ejecución. Los ejemplos presentados en la sección de discusión demuestra distintas maneras en las que podemos pausar un thread; además, de lo anterior distinguiremos las situaciones donde se generan excepciones por el uso inadecuado de valores de argumento para el método Thread.Sleep.

1. Problema

Esta vez debemos consultar y aplicar un método que facilite la detención temporal o pausa de un método en ejecución (en la receta anterior -Cómo Crear un Thread- aprendimos cómo iniciar un thread usando la clase Thread y el delegado ThreadStart).

2. Solución

El equipo de programadores de Ad Infinitum Systems siempre están preparados y nos han traído una solución simple y directa para solventar el problema planteado en la sección 1. La solución consiste en usar el método estático Sleep de la clase Thread. En la siguiente sección extenderemos este conocimiento a partir de una discusión que compromete el uso declarativo de Thread.Sleep, casos especiales, excepciones, y ejemplos.

3. Discusión de la Solución

3.1 Método Sleep(int)

Este método se haya definido en la clase Thread [3]. Su naturaleza declarativa indica que se trata de un método estático. Aquí está su firma [5]:

public static void Sleep(int millisecondsTimeout)

Descripción puntual:
  • Tipo de retorno: void
  • Parámetros:
    • int millisecondsTimeout: pausa por una cantidad de tiempo medida en milisegundos.
En cuanto al parámetro millisecondsTimeout es importante manifestar que el intento de pasar un valor menor a cero o distinto a la constante Infinite [8] (clase TimeOut [9]) generará la excepción ArgumentOutOfRangeException [10].


Continuando, cuando especificamos cero (0) como argumento para Sleep, el thread da paso de ejecución a cualquier otro thread de igual prioridad que esté listo a ejecutarse. En caso de que no sea así, la ejecución del thread no es suspendida y continua su ejecución [5].

3.2 Método Sleep(TimeSpan)

Esta versión sobrecargada del método Sleep funciona de manera similar a la versión presentada en la sección 3.1; sin embargo, el tipo del parámetro, TimeSpan [6], permite especificar un tiempo un intervalo de tiempo (por ejemplo, en horas, minutos, y segundos).


Para comprender el uso de este método, empecemos con el siguiente ejemplo:


Archivo de código fuente UsoSleepConTimeSpan.cs [enlace alternativo]:

En la línea 12 creamos una instancia de la estructura TimeSpan para crear un intervalo de 2 segundos. La variable intervalo es pasada como argumento al método Thread.Sleep. Con esta configuración el thread principal se detendrá por 2 segundos.

Compilación:


  1. csc /target:exe UsoSleepConTimeSpan.cs

Ejecución assembly:


  1. .\UsoSleepConTimeSpan.exe

> Prueba de ejecución.

Resultado:
Prueba ejecución assembly UsoSleepConTimeSpan.exe
Figura 1. Prueba ejecución assembly UsoSleepConTimeSpan.exe.

3.3 Ejemplos

A continuación presento tres ejemplos de uso del método Sleep. Estos ejemplos comprenden un soporte práctico para la comprensión y utilidad de este método en diferentes escenarios de ejecución.

3.3.1 Uso básico de Sleep(int)

Archivo de código fuente UsoSleep.cs [enlace alternativo]:
Básicamente con este código ejemplo se demuestra un uso básico del método Sleep. La línea a destacar se haya en la posición 14, en donde pasamos la literal entera 2000 como argumento del método Sleep. Cada iteración del ciclo for (líneas 10-15) se pausará por dos (2) segundos. Finalizado el ciclo anterior, el método Main común y corriente.

Compilación:


  1. csc /target:exe UsoSleep.cs

Ejecución assembly:


  1. .\UsoSleep.exe

> Prueba de ejecución.

Resultado:
Prueba de ejecución del assembly UsoSleep.exe.
Figura 2. Prueba de ejecución del assembly UsoSleep.exe.

3.3.2 Pausar dos threads

En este ejemplo vamos a ver algo interesante, detendremos en diferentes medidas de tiempo dos threads: Main y un nuevo thread que crearemos.

Archivo de código fuente UsoSleepConThread.cs [enlace alternativo]:

En la línea 10 creamos una instancia de Thread a la que pasamos como argumento una instancia del delegado ThreadStart, el cual encapsula al método EscribirMundo. En cada iteración del ciclo for (líneas 14-18), se realiza una pausa de 1 segundos, mientras que de forma paralela el método EscribirMundo también realiza una pausa por cada iteración. (Esto va a crear un efecto alternante entre las salidas de texto que se genera con la llamada de Console.WriteLine)

Compilación:


  1. csc /target:exe UsoSleepConThread.cs

Ejecución assembly:


  1. .\UsoSleepConThread.exe

> Prueba de ejecución.

Resultado:
Prueba de ejecución assembly UsoSleepConThread.exe
Figura 3. Prueba de ejecución assembly UsoSleepConThread.exe.

3.3.3 Precisión con Thread.Sleep

Tercer ejemplo en donde podremos medir la precisión del método Sleep.

Archivo de código fuente PrecisionThreadSleep.cs [enlace alternativo]:

En la línea 13 creamos un cronómetro. Este cronómetro nos va ayudar medir el tiempo que tarda las pausas que se realizan en las líneas 15, 24, y 31. Por cada pausa, en las líneas subsiguientes a cada una, se muestra un resumen del tiempo que ha tardado la pausa (con la hora actual).

Compilación:


  1. csc /target:exe PrecisionThreadSleep.cs

Ejecución assembly:


  1. .\PrecisionThreadSleep.exe

> Prueba de ejecución.

Resultado:
Prueba de ejecución assembly PrecisionThreadSleep.exe
Figura 4. Prueba de ejecución assembly PrecisionThreadSleep.exe.

4. Práctica: Código Fuente C#

En esta sección práctica incluiré lo que podría considerarse un afianzamiento tildado de los conceptos teóricos y prácticos (a pesar de los cuatro {4} ejemplos presentados en la sección 3).

Archivo de código fuente ImpresionNumerosConRetraso.cs [enlace alternativo]:
Compilación:


  1. csc /target:exe ImpresionNumerosConRetraso.cs

Ejecución assembly:


  1. .\ImpresionNumerosConRetraso.exe

> Prueba de ejecución.

Resultado:
Prueba de ejecución assembly ImpresionNumerosConRetraso
Figura 5. Prueba de ejecución assembly ImpresionNumerosConRetraso.exe.

5. Conclusiones

Ha quedado demostrado por medio de esta receta que es posible detener la ejecución de un thread que se esté ejecutando. La clase Thread es la construcción lógica que provee el método indicado para esta tarea: Sleep. En los ejemplos quedó plasmado el uso de este método estático de manera muy práctica y esencial, para que en próximas recetas relacionadas con multithreading contemos con más herramientas que nos acerque a la comprensión de conceptos más abstractos.

6. Glosario

  • Ejecución
  • Excepción
  • Infinite
  • Multithreading
  • Sleep
  • Thread

7. Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: Pausing and Resuming Threads - http://msdn.microsoft.com/en-us/library/tttdef8x(v=vs.110).aspx
[3]: Thread Class (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.thread(v=vs.110).aspx
[4]: ThreadStart Delegate (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.threadstart.aspx
[5]: Thread.Sleep Method (Int32) (System.Threading) - http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.110).aspx
[6]: TimeSpan Structure (System) - http://msdn.microsoft.com/en-us/library/System.TimeSpan(v=vs.110).aspx
[7]: Pausing a thread in C# - http://www.dotnetheaven.com/article/pausing-a-thread-in-csharp
[8]: Timeout.Infinite Field (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.timeout.infinite(v=vs.110).aspx
[9]: Timeout Class (System.Threading) - http://msdn.microsoft.com/en-us/library/System.Threading.Timeout(v=vs.110).aspx
[10]: ArgumentOutOfRangeException Class (System) - http://msdn.microsoft.com/en-us/library/system.argumentoutofrangeexception(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

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