Como redefinir um cronômetro em C #?

114

Há três Timerclasses que eu estou ciente de, System.Threading.Timer, System.Timers.Timer, e System.Windows.Forms.Timer, mas nenhum deles tem uma .Reset()função que iria repor o tempo decorrido atual para 0.

Existe uma classe BCL que possui essa funcionalidade? Existe uma maneira não hack de fazer isso? (Eu pensei que talvez mudar o limite de tempo nele pudesse redefini-lo) Pensei em como seria difícil reimplementar uma Timerclasse que tivesse essa funcionalidade, ou como fazer isso de forma confiável com uma das classes BCL?

Matthew Scharley
fonte
3
Usando a solução de JP use um método de extensão
benPearce
Eu também tenho a mesma necessidade de redefinir e pelas mesmas razões mencionadas, FileSystemWatcher é desagradável e inconveniente de usar
John Lewin,
Se você usar o Cronômetro para um cronômetro e for com a resposta do método de extensão, tome cuidado porque o método de extensão Stopwatch.Restart está chegando no .NET 4.0. msdn.microsoft.com/en-us/library/…
si618

Respostas:

148

Eu sempre faço ...

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

... isso é um hack? :)

Por comentário, em Threading.Timer, é o método Change ...

dueTime Tipo: System.Int32A quantidade de tempo de atraso antes de invocar o método de retorno de chamada especificado quando o Timer foi construído, em milissegundos. Especifique Timeout.Infinitepara evitar que o cronômetro seja reiniciado. Especifique zero (0) para reiniciar o cronômetro imediatamente.

JP Alioto
fonte
O outro problema é que só se preocupa com Forms.Timer, e meu aplicativo não tem GUI (Application.Start () sem parâmetros), então ACHO que a classe Threading.Timer é melhor por outros motivos, mas bom ponto.
Matthew Scharley
3
@Matthew: Consulte msdn.microsoft.com/en-us/magazine/cc164015.aspx para uma discussão sobre as várias classes de cronômetro e quando usá-los é apropriado. Em geral, porém, Forms.Timersó deve ser usado com uma GUI. No entanto, além de Forms.Timere Threading.Timerhá também Timers.Timer.
Brian
60

Todos os temporizadores têm o equivalente aos métodos Start () e Stop (), exceto System.Threading.Timer.

Portanto, um método de extensão como ...

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

... é uma maneira de fazer isso.

Dan
fonte
1
Não estou procurando medir o tempo decorrido. Meu caso de uso exato para isso é que tenho um FileSystemWatcher observando um diretório e quero capturar grupos de alterações (ou seja, alterações feitas, por exemplo, 5 segundos entre si). A teoria é que a primeira mudança inicia um cronômetro que é zerado com cada mudança até que eventualmente seja acionado e feche o grupo.
Matthew Scharley
Sim, percebi isso quando reli sua pergunta. Editou minha resposta.
Dan
Isso funciona e é importante notar que não funcionará se você apenas ligar timer.Start(). Fiz esta consulta Linqpad para testá-lo. Tente removê timer.Stop-lo e você verá a diferença.
Praia Jared
30

Para System.Timers.Timer, de acordo com a documentação do MSDN, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Se o intervalo for definido após o início do cronômetro, a contagem será zerada. Por exemplo, se você definir o intervalo para 5 segundos e, em seguida, definir a propriedade Enabled como true, a contagem começará no momento em que Enabled for definido. Se você reconfigurar o intervalo para 10 segundos quando a contagem for de 3 segundos, o evento Elapsed será gerado pela primeira vez 13 segundos após Enabled ter sido definido como true.

Assim,

    const double TIMEOUT = 5000; // milliseconds

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

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
mMontu
fonte
1
O problema aqui é que nem sempre você sabe no momento em que deseja zerar se o cronômetro já está funcionando ou não. Então, você teria que fazer aTimer.Interval = TIMEOUT e um aTimer.Start (). Portanto, em geral, uma função de redefinição acima usa menos linhas e variáveis. Grande adição embora.
e-motiv
1
@ RU-Bn O OP afirma claramente " uma função .Reset () que redefiniria o tempo decorrido atual para 0. " - não menciona que se destina ao uso em um aplicativo mal projetado, onde você nem sabe se o cronômetro está funcionando. Verifique também o comentário do autor (mais de 4 anos atrás): " A teoria é que a primeira mudança inicia um cronômetro que é zerado a cada mudança até que eventualmente dispara e fecha o grupo. ". Obrigado pelo voto negativo, de qualquer maneira.
mMontu
Eu também vi um problema assim. O que fiz foi: aTimer.Interval = aTimer.Interval. Isso fez com que o loop estivesse acontecendo. Não sei por que, mas funciona ...
Herman Van Der Blom
7

Você pode escrever um método de extensão chamado Reset (), que

  • chama Stop () - Start () para Timers.Timer e Forms.Timer
  • chama Change for Threading.Timer
Gishu
fonte
5

Acabei de atribuir um novo valor ao cronômetro:

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

Isso funciona bem para mim.

no topo do código, defina o cronômetro: 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
fonte
5

Para maior clareza, uma vez que alguns outros comentários estão incorretos, ao usar a System.Timersconfiguração Enabled para true , redefinirá o tempo decorrido. Acabei de testar o comportamento com o seguinte:

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");
}

Gostaria de inserir texto na caixa de texto repetidamente e o cronômetro funcionaria apenas 3 segundos após o último pressionamento de tecla. Também é sugerido nos documentos, como você verá: chamar Timers.Start()simplesmente define Enabled como true.

E para ter certeza, ao qual eu deveria ter ido direto desde o início, você verá na fonte de referência do .NET que, se habilitar um timer já Enabled, ele chama o UpdateTimer()método privado , que chama internamente Change().

NickSpag
fonte
Não, você está errado. O UpdateTtimermétodo privado é chamado se e somente se o valor atual de Enablednão for igual ao novo value.
Nicolò Carandini
3

Para um Timer (System.Windows.Forms.Timer).

Os métodos .Stop e .Start funcionaram como um reset.

elmsoftware
fonte
1

Outra forma alternativa de redefinir o windows.timer é usar o contador, da seguinte maneira:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

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

Portanto, se você pretende repetir a cada 1 segundo, pode definir o intervalo do cronômetro em 100 ms e testar o contador em 10 ciclos.

Isso é adequado se o cronômetro deve esperar por alguns processos que podem ser encerrados em um intervalo de tempo diferente.

ivan
fonte
1

Eu faço isso

//Restart the timer
queueTimer.Enabled = true;
Rissa
fonte
Isso apenas permite. Mesmo que tenha sido desativado anteriormente, reativá-lo não altera o tempo decorrido que foi coletado até aquele ponto.
vapcguy
1

Você pode fazer timer.Interval = timer.Interval

Ella Sharakanski
fonte