¿Cómo restablecer un temporizador en C #?

114

Hay tres Timerclases que yo sepa, System.Threading.Timer, System.Timers.Timer, y System.Windows.Forms.Timer, pero ninguno de ellos tiene una .Reset()función que se restablezca el tiempo transcurrido actual en 0.

¿Existe una clase BCL que tenga esta funcionalidad? ¿Hay alguna forma de hacerlo sin piratear? (Pensé que tal vez cambiar el límite de tiempo podría restablecerlo) ¿Pensó en lo difícil que sería volver a implementar una Timerclase que tuviera esta funcionalidad, o cómo hacerlo de manera confiable con una de las clases BCL?

Matthew Scharley
fuente
3
Usando la solución de JP, use un método de extensión
benPearce
Yo también tengo la misma necesidad de reinicio y por las mismas razones mencionadas, FileSystemWatcher es desagradable e inconveniente de usar
John Lewin
Si usa Stopwatch para un temporizador y sigue la respuesta del método de extensión, tenga cuidado porque el método de extensión Stopwatch.Restart viene en .NET 4.0. msdn.microsoft.com/en-us/library/…
si618

Respuestas:

148

Siempre hago ...

myTimer.Stop();
myTimer.Start();

... eso es un truco? :)

Por comentario, en Threading.Timer, es el método de cambio ...

dueTime Type: System.Int32la cantidad de tiempo de demora antes de invocar el método de devolución de llamada especificado cuando se construyó el temporizador, en milisegundos. Especifique Timeout.Infinitepara evitar que el temporizador se reinicie. Especifique cero (0) para reiniciar el temporizador inmediatamente.

JP Alioto
fuente
El otro problema es que solo funciona con Forms.Timer, y mi aplicación no tiene GUI (Application.Start () sin parámetros), así que CREO que la clase Threading.Timer es mejor por otras razones, pero buen punto.
Matthew Scharley
3
@Matthew: consulte msdn.microsoft.com/en-us/magazine/cc164015.aspx para obtener una descripción de las distintas clases de temporizadores y cuándo es apropiado usarlas. Sin embargo, en general, Forms.Timersolo debe usarse con una GUI. Sin embargo, además Forms.Timery Threading.Timertambién hay Timers.Timer.
Brian
60

Todos los temporizadores tienen el equivalente a los métodos Start () y Stop (), excepto System.Threading.Timer.

Entonces, un método de extensión como ...

public static void Reset(this Timer timer)
{
  timer.Stop();
  timer.Start();
}

... es una forma de hacerlo.

Dan
fuente
1
No busco medir el tiempo transcurrido. Mi caso de uso exacto para esto es que tengo un FileSystemWatcher mirando un directorio y quiero capturar grupos de cambios (es decir, cambios realizados dentro de, por ejemplo, 5 segundos entre sí). La teoría es que el primer cambio inicia un temporizador que se reinicia con cada cambio hasta que finalmente se activa y cierra el grupo.
Matthew Scharley
Sí, me di cuenta de eso cuando releí tu pregunta. Edité mi respuesta.
Dan
Esto funciona y es importante tener en cuenta que no funcionará si solo llama timer.Start(). Hice esta consulta de Linqpad para probarlo. Intente quitarlo timer.Stopy verá la diferencia.
Playa Jared
30

Para System.Timers.Timer, según la documentación de MSDN, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Si el intervalo se establece después de que se haya iniciado el temporizador, la cuenta se reinicia. Por ejemplo, si establece el intervalo en 5 segundos y luego establece la propiedad Enabled en verdadero, el recuento comienza en el momento en que se establece Enabled. Si restablece el intervalo a 10 segundos cuando la cuenta es de 3 segundos, el evento Transcurrido se genera por primera vez 13 segundos después de que Activado se estableció en verdadero.

Entonces,

    const double TIMEOUT = 5000; // milliseconds

    aTimer = new System.Timers.Timer(TIMEOUT);
    aTimer.Start();     // timer start running

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
mMontu
fuente
1
El problema aquí es que no siempre sabe en el momento en que desea reiniciar si el temporizador ya está funcionando o no. Entonces, tendría que hacer aTimer.Interval = TIMEOUT y aTimer.Start (). Entonces, en general, una función de reinicio anterior usa menos líneas y variables. Sin embargo, gran adición.
e-motiv
1
@ RU-Bn El OP establece claramente " una función .Reset () que restablecería el tiempo transcurrido actual a 0 ". - no menciona que está destinado a usarse en una aplicación de diseño deficiente en la que ni siquiera se sabe si el temporizador está funcionando. Consulte también el comentario del autor (hace más de 4 años): " La teoría es que el primer cambio inicia un temporizador que se reinicia con cada cambio hasta que finalmente se activa y cierra el grupo ". Gracias por el voto negativo, de todos modos.
mMontu
También vi un problema como ese. Lo que hice fue: aTimer.Interval = aTimer.Interval. Eso provocó que el bucle continuara. Me gana por qué, pero funciona ...
Herman Van Der Blom
7

Podría escribir un método de extensión llamado Reset (), que

  • llamadas Stop () - Start () para Timers.Timer y Forms.Timer
  • llamadas Change for Threading.Timer
Gishu
fuente
5

Acabo de asignar un nuevo valor al temporizador:

mytimer.Change(10000, 0); // reset to 10 seconds

Funciona bien para mí.

en la parte superior del código, defina el temporizador: System.Threading.Timer myTimer;

if (!active)
        {
            myTimer= new System.Threading.Timer(new TimerCallback(TimerProc));
        }
        myTimer.Change(10000, 0);
        active = true;

private void TimerProc(object state)
    {
        // The state object is the Timer object.
        System.Threading.Timer t = (System.Threading.Timer)state;
        t.Dispose();
        Console.WriteLine("The timer callback executes.");
        active = false;
        //action to do when timer is back to zero
    }
Quispie
fuente
5

Para mayor claridad, ya que algunos otros comentarios son incorrectos, cuando se utiliza el System.Timersajuste Activado en verdadero, se restablecerá el tiempo transcurrido. Acabo de probar el comportamiento con lo siguiente:

Timer countDown= new Timer(3000);

Main()
{
    TextBox.TextDidChange += TextBox_TextDidChange;
    countdown.Elapsed += CountDown_Elapsed;
}

void TextBox_TextDidChange(Object sender, EventArgs e)
{
    countdown.Enabled = true;
}

void CountDown_Elapsed(object sender, EventArgs e)
{
    System.Console.WriteLine("Elapsed");
}

Ingresaría texto en el cuadro de texto repetidamente y el temporizador solo funcionaría 3 segundos después de la última pulsación de tecla. También se insinúa en los documentos, como verá: la llamada Timers.Start()simplemente establece Enabled en verdadero.

Y para estar seguro, a lo que debería haber ido directamente desde el principio, verá en la fuente de referencia de .NET que si habilita un temporizador ya habilitado, llama al UpdateTimer()método privado , que llama internamente Change().

NickSpag
fuente
No, tu estas equivocado. El UpdateTtimermétodo privado se llama si y solo si el valor actual de Enabledno es igual al nuevo value.
Nicolò Carandini
3

Para un temporizador (System.Windows.Forms.Timer).

Los métodos .Stop, luego .Start funcionaron como un reinicio.

elmsoftware
fuente
1

Otra forma alternativa de restablecer el temporizador de windows es usando el contador, de la siguiente manera:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

private void mTimer_Tick()
{
  tmrCtr++;
  //perform task
}  

Entonces, si tiene la intención de repetir cada segundo, puede configurar el intervalo del temporizador en 100 ms y probar el contador en 10 ciclos.

Esto es adecuado si el temporizador debe esperar a que algunos procesos finalicen en un lapso de tiempo diferente.

ivan
fuente
1

hago esto

//Restart the timer
queueTimer.Enabled = true;
Rissa
fuente
Esto simplemente lo habilita. Incluso si se deshabilitó de antemano, la reactivación no cambia el tiempo transcurrido que se había recopilado hasta ese momento.
vapcguy
1

Tu puedes hacer timer.Interval = timer.Interval

Ella Sharakanski
fuente