martes, 24 de junio de 2014

Receta No. 4-4 en C#: Ejecución de un Método en Tiempo Específico

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En la receta previa aprendimos a ejecutar un método de forma periódica usando varios artefactos de la biblioteca base de clases de .NET Framework. Este conocimiento nos va a ser de enorme utilidad para desarrollar nuestra siguiente receta: Ejecución de un método en un momento específico. Usaremos una de las versiones sobrecargadas de los constructor de la clase System.Threading.Timer (al que podríamos referirnos como un temporizador de threads) que facilita la especificación del disparador del evento de inicio de ejecución del método. Empecemos a preparar esta llamativa receta en C#.

1. Problema

Necesitamos ejecutar un método en un thread nuevo, y, que además se ejecute en un determinado tiempo. (Este conocimiento nos servirá para conceptualizar y practicar los esenciales para la programación de tareas en un momento específico del día y/o cada cierta periodicidad.)

2. Solución

La receta anterior fue muy interesante, pues aprendimos a ejecutar un método periódicamente y los artefactos que utilizamos en esa receta nos dieron las primeras pistas de ejecución asincrónica de métodos, estamos hablando System.Threading.Timer y el delegado TimerCallback (System.Threading). Relativamente ya tenemos la solución en nuestras manos: ahora lo que tenemos que hacer es explorar otra de las versiones del constructor de la clase Timer (y es lo que haremos ahora la sección de discusión de la solución).

3. Discusión de la Solución

La creación de un método que se ejecute en un determinado tiempo puede facilitarnos la automatización de tareas rutinarias; por ejemplo, la generación de copias de seguridad a una hora de baja demanda o suspensión temporal de un servicio o aplicación Web que hayamos creado. También podríamos pensar en la creación de una aplicación que repita eventos rutinarios: por ejemplo a programación de una alarma para salir a trabajar o a estudiar en un momento especificado.


Esto lo podemos lograr gracias a uno de los constructores disponibles en la clase Timer [4]:


public Timer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period)


Descripción puntual:

  • TimeCallback callback: delegado TimerCallback que encapsula el método a ser ejecutado.
  • Object state: contenedor de información útil para el método a ser ejecutado. Puede ser null.
  • TimeSpan dueTime: corresponde con el momento específico en que será ejecutado el método encapsulado por el delegado TimerCallback [2]. Podemos especificar, por ejemplo, el tiempo de ejecución a través de la diferencia entre la fecha y hora actual (DateTime.Now [5]) y el instante en el que se debe ejecutar el método (e.g., una hora y media después, o pasado un día).

    Se debe tener en cuenta que si especificamos -1 se deshabilitará la ejecución del método, o en caso de que sea 0 (TimeSpan(0)) se iniciará le ejecución del método al instante.

  • TimeSpan period: intervalo de tiempo por cada repetición del método encapsulado por el callback. Al especificar System.Threading.Timeout.Infinite [6] o TimeSpan(-1) se deshabilita la periodicidad de ejecución.
Ejemplo de uso:


Creamos un ejemplo sencillo pero útil para comprender el uso de este constructor.


Archivo C# UsoTimerEjecucionProgramada.cs:

Empezamos por crear un archivo donde guardaremos los registros periódicos en la línea 12. Creamos el delegado TimerCallback (línea 17) que encapsula al método GuardarRegistroEnArchivo. Creamos el temporizador (Timer) con la siguiente para parametrización:
  • Instancia TimerCallback
  • null: no se pasa ningún contenedor de datos para el método encapsulado en el delegado.
  • new TimeSpan(0, 0, 7): la invocación del método GuardarRegistroEnArchivo iniciará con un retraso de 7 segundos.
  • new TimeSpan(0, 0, 5): el método GuardarRegistroEnArchivo se ejecutará cada 5 segundos.
Compilación:

  1. csc /target:exe UsoTimerEjecucionProgramada.cs

Ejecución assembly:

  1. .\UsoTimerEjecucionProgramada.exe

Resultado:
Compilación y ejecución assembly UsoTimerEjecucionProgramada.exe
Figura 1. Compilación y ejecución assembly UsoTimerEjecucionProgramada.exe.

4. Práctica: Código C#

El código fuente C# que se muestra a continuación demuestra cómo ejecutar un método (una tarea) pasados 10 segundos de la hora actual, y se repetirá una única vez.

Archivo C# EjecucionTareaProgramada.cs:

En la línea 11 creamos un intervalo de tiempo de 10 segundos; así:

TimeSpan tiempoEspera = new TimeSpan (0010);


Creamos una instancia anónima de Timer (líneas 16-23) a la cual le pasamos un delegado con un método anónimo para mostrar un mensaje en que el temporizador se ejecuta. Este temporizador se ejecutará sólo una vez:


TimeSpan(-1)

Compilación:


  1. csc /target:exe EjecucionTareaProgramada.cs

Ejecución assembly:


  1. .\EnsambladorRegex.exe

Prueba de ejecución:
Compilación y ejecución assembly EjecucionTareaProgramada.exe
Figura 2. Compilación y ejecución assembly EjecucionTareaProgramada.exe.

5. Conclusiones

La receta demostró el uso del constructor Timer(TimerCallback, Object, TimeSpan, TimeSpan) para la creación de un temporizador que facilita la ejecución de un método en un momento determinado cada cierta periodicidad. Este tipo de conocimiento nos puede ser útil para la programación y automatización de tareas rutinarias (e.g., generación de copias de seguridad, alarmas) en aplicaciones que lo requieran así.

Glosario

  • Alarma
  • Ejecución
  • Programación
  • Temporizador
  • Thread
  • Timer

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]: TimerCallback Delegate (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.timercallback(v=vs.110).aspx
[3]: Timer Class (System.Threading) - http://msdn.microsoft.com/en-us/library/System.Threading.Timer(v=vs.110).aspx
[4]: Timer Constructor (TimerCallback, Object, TimeSpan, TimeSpan) (System.Threading) - http://msdn.microsoft.com/en-us/library/ah1h85ch(v=vs.110).aspx
[5]: DateTime.Now Property (System) - http://msdn.microsoft.com/en-us/library/system.datetime.now(v=vs.110).aspx
[6]: Timeout.Infinite Field (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.timeout.infinite(v=vs.110).aspx


M

No hay comentarios:

Publicar un comentario

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