HOWTO · Csharp
Restablecer temporizador en C#
Este artículo discutirá cómo restablecer un temporizador usando el lenguaje de programación C#.
En esta página
Para reiniciar el intervalo de un temporizador en C#, llama a Stop() y luego a Start() en un System.Timers.Timer. El tipo no tiene un método Reset(). Configura AutoReset según quieras que se produzca un único evento Elapsed o que se repita; esa propiedad no reinicia bajo demanda una cuenta regresiva en curso.
¿Qué comportamiento de temporizador de C# necesitas?
Elige un temporizador de una sola ejecución cuando una operación deba realizarse una vez después de una demora, o cuando el código programe explícitamente el siguiente intervalo. Establece AutoReset en false y luego usa Stop() y Start() cada vez que necesites iniciar un intervalo nuevo. Para tareas periódicas, establece AutoReset en true y deja que el temporizador genere el evento Elapsed después de cada intervalo.
Si el temporizador ya está en marcha y necesitas aplazar el siguiente evento, detenlo y vuelve a iniciarlo. Iniciar un temporizador que ya está habilitado no ofrece una operación de reinicio independiente. Configura el intervalo en milisegundos y elige una duración positiva adecuada para la tarea; un temporizador sirve para programar devoluciones de llamada, no para medir el tiempo transcurrido con precisión.
Cómo System.Timers.Timer gestiona los eventos Elapsed
System.Timers.Timer genera su evento Elapsed una vez transcurrido el Interval configurado. Enabled indica si el temporizador está en marcha; Start() lo habilita y Stop() lo deshabilita. El controlador del evento recibe un valor ElapsedEventArgs, que incluye la hora de la señal. Los controladores se ejecutan de forma asíncrona, por lo que pueden solaparse si una tarea recurrente tarda más que el intervalo. Protege el estado compartido y no supongas que la devolución de llamada se ejecuta en el subproceso de la interfaz de usuario.
AutoReset es una propiedad booleana. Con true, el temporizador programa eventos Elapsed posteriores según el intervalo. Con false, genera un evento y luego se detiene. Esta propiedad controla la repetición; no es una orden para reiniciar la cuenta regresiva actual. Si un temporizador de una sola ejecución necesita otro intervalo, llama explícitamente a Start() después de gestionar el evento.
Reiniciar un temporizador de una sola ejecución con Stop() y Start()
Si el temporizador de una sola ejecución está en marcha, llama a Stop() para cancelar la programación pendiente y luego a Start() para iniciar un intervalo nuevo. Este es el método práctico para reiniciarlo. Si el temporizador ya generó su evento con AutoReset establecido en false, llama a Start() para programar otro intervalo. Configura AutoReset antes de iniciarlo para que su comportamiento esté claro desde el principio.
Recuerda que las devoluciones de llamada del temporizador son asíncronas. Puede que una devolución de llamada ya esté en cola cuando otra parte del programa detenga el temporizador, así que coordina el cierre y los datos compartidos cuando esa diferencia sea relevante. Mantén breve el controlador o delega las tareas largas a un trabajador controlado para evitar que los intervalos recurrentes coincidan con trabajo aún pendiente.
Usar AutoReset para intervalos recurrentes
Establece AutoReset = true para un intervalo recurrente, por ejemplo, para consultar datos o actualizar periódicamente un valor. Cada evento Elapsed se programa según el intervalo del temporizador. Establécela en false cuando necesites un solo evento y quieras decidir explícitamente cuándo iniciar el siguiente intervalo. Ninguno de los dos valores permite consultar una cuenta regresiva ni cambiar sobre la marcha el intervalo de un evento ya programado; detén y vuelve a iniciar el temporizador para programar un intervalo nuevo.
No uses un temporizador recurrente como reloj preciso. La carga del grupo de subprocesos puede retrasar la programación, y la devolución de llamada quizá no comience exactamente en el milisegundo solicitado. Si cada operación debe terminar antes de que empiece la siguiente, programa un intervalo de una sola ejecución cuando finalice la operación o sincroniza el trabajo.
Detener y liberar el temporizador de forma segura
Llama a Stop() cuando el temporizador ya no deba programar eventos. Cuando termine la operación propietaria, llama a Dispose() para liberar los recursos del temporizador. Detenerlo y liberarlo resuelven problemas distintos: Stop() finaliza la programación activa, mientras que Dispose() termina la vida útil del temporizador. No reinicies un temporizador liberado; crea una instancia nueva si otra operación necesita uno.
Como Elapsed se ejecuta de forma asíncrona, detener el temporizador no cancela un controlador que ya esté ejecutándose. Si el cierre debe esperar a que termine una devolución de llamada, coordínate con ese controlador mediante un mecanismo de sincronización adecuado para la aplicación. Mantén vivo el temporizador mientras su controlador pueda utilizarlo y anula la suscripción a los controladores cuando un temporizador de larga duración ya no los necesite.
Ejemplo completo: reiniciar un temporizador de una sola ejecución
Este ejemplo completo genera un evento después de dos segundos, inicia un intervalo nuevo desde ese controlador y termina después del segundo evento. AutoReset = false hace que cada evento se produzca una sola vez; Stop() y Start() programan explícitamente el segundo intervalo. La señal de finalización permite que Main espere a que terminen ambas devoluciones de llamada antes de realizar la limpieza.
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
using System;
using System.Threading;
using System.Timers;
class TimerRestartExample
{
static void Main()
{
using (var completed = new ManualResetEventSlim())
using (var timer = new System.Timers.Timer(2000))
{
int eventCount = 0;
timer.AutoReset = false;
timer.Elapsed += (sender, args) =>
{
eventCount++;
Console.WriteLine("Elapsed event " + eventCount);
if (eventCount == 1)
{
timer.Stop();
timer.Start();
}
else
{
completed.Set();
}
};
timer.Start();
completed.Wait();
timer.Stop();
}
}
}
Elapsed event 1
Elapsed event 2
La ejecución proporcionada completó correctamente la prueba en tiempo de ejecución e imprimió los dos eventos Elapsed que aparecen arriba. En una aplicación, elige un intervalo y una estrategia de finalización adecuados para su ciclo de vida; un servicio o una interfaz de usuario pueden seguir en funcionamiento después de un evento del temporizador, en lugar de esperar y terminar como hace esta demostración.