Как сбросить таймер на C #?

114

Есть три Timerкласса , которые я знаю, System.Threading.Timer, System.Timers.Timerи System.Windows.Forms.Timer, но ни один из них не имеет .Reset()функции , которая будет сбросить текущее время , прошедшее до 0.

Есть ли класс BCL, у которого есть эта функция? Есть ли способ сделать это без взлома? (Я подумал, что, возможно, изменение ограничения по времени может сбросить его). Подумал, насколько сложно будет повторно реализовать Timerкласс, имеющий эту функцию, или как надежно сделать это с помощью одного из классов BCL?

Мэтью Шарли
источник
3
Используя решение JP, используйте метод расширения
benPearce
У меня такая же потребность в сбросе, и по тем же причинам, упомянутым выше, FileSystemWatcher неприятен и неудобен в использовании
Джон Левин
Если вы используете секундомер для таймера и используете ответ метода расширения, будьте осторожны, потому что метод расширения Stopwatch.Restart входит в .NET 4.0. msdn.microsoft.com/en-us/library/…
si618,

Ответы:

150

Я всегда делаю ...

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

... это взлом? :)

В комментарии к Threading.Timer это метод Change ...

dueTime Тип: System.Int32время задержки перед вызовом метода обратного вызова, указанного при создании Timer, в миллисекундах. Уточнить Timeout.Infinite чтобы таймер не перезапускался. Укажите ноль (0) для немедленного перезапуска таймера.

JP Alioto
источник
Другая проблема заключается в том, что работает только с Forms.Timer, а у моего приложения нет графического интерфейса (Application.Start () без параметров), поэтому я ДУМАЮ, что класс Threading.Timer лучше по другим причинам, но хороший момент.
Мэтью Шарли,
3
@Matthew: См. Msdn.microsoft.com/en-us/magazine/cc164015.aspx для обсуждения различных классов таймера и того, когда их использовать. В общем, однако, Forms.Timerследует использовать только с графическим интерфейсом. Впрочем, кроме того Forms.Timerи Threading.Timerесть еще Timers.Timer.
Брайан
60

Все таймеры имеют эквивалент методов Start () и Stop (), за исключением System.Threading.Timer.

Итак, метод расширения, такой как ...

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

... это один из способов решить эту проблему.

Дэн
источник
1
Я не собираюсь измерять прошедшее время. Мой точный вариант использования для этого заключается в том, что у меня есть FileSystemWatcher, наблюдающий за каталогом и хочу улавливать группы изменений (т.е. изменения, сделанные, например, в пределах 5 секунд друг от друга). Теория состоит в том, что первое изменение запускает таймер, который сбрасывается при каждом изменении, пока в конечном итоге не сработает и не закроет группу.
Мэтью Шарли,
Да, я заметил это, когда перечитал твой вопрос. Отредактировал свой ответ.
Дэн
Это работает, и важно отметить, что это не сработает, если вы только позвоните timer.Start(). Я сделал этот запрос Linqpad, чтобы проверить его. Попробуйте удалить timer.Stopего, и вы увидите разницу.
Джаред Бич
30

Ведь System.Timers.Timerсогласно документации MSDN http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Если интервал установлен после запуска таймера, счетчик сбрасывается. Например, если вы установите интервал в 5 секунд, а затем установите для свойства Enabled значение true, счет начнется в то время, когда установлено значение Enabled. Если вы сбрасываете интервал на 10 секунд, когда счетчик равен 3 секундам, событие Elapsed возникает впервые через 13 секунд после того, как для Enabled было установлено значение true.

Так,

    const double TIMEOUT = 5000; // milliseconds

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

    :
    :

    aTimer.Interval = TIMEOUT;  // restart the timer
мМонту
источник
1
Проблема здесь в том, что в момент сброса вы не всегда знаете, запущен ли таймер или нет. Итак, вам нужно будет выполнить aTimer.Interval = TIMEOUT и aTimer.Start (). Таким образом, в целом вышеописанная функция сброса использует меньше строк и переменных. Впрочем, отличное дополнение.
e-motiv
1
@ RU-Bn OP четко указывает " функцию .Reset (), которая сбрасывает текущее прошедшее время на 0 ". - не упоминается, что он предназначен для использования в плохо спроектированном приложении, где вы даже не знаете, работает ли таймер. Также проверьте комментарий автора (более 4 лет назад): « Теория состоит в том, что первое изменение запускает таймер, который сбрасывается при каждом изменении, пока в конечном итоге не сработает и не закроет группу. ». В любом случае, спасибо за голосование "против".
mMontu
Я тоже видел такую ​​проблему. Я сделал следующее: aTimer.Interval = aTimer.Interval. Это привело к тому, что цикл продолжался. Лучше меня почему, но это работает ...
Герман Ван Дер Блом
7

Вы можете написать метод расширения под названием Reset (), который

  • вызывает Stop () - Start () для Timers.Timer и Forms.Timer
  • вызывает Change for Threading.Timer
Gishu
источник
5

Я только что присвоил таймеру новое значение:

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

Он отлично работает для меня.

в верхней части кода определите таймер: 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
источник
5

Для ясности, поскольку некоторые другие комментарии неверны, при использовании System.Timersнастройки Enabled на true , истекшее время будет сброшено. Я только что проверил поведение следующим образом:

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

Я вводил текст в текстовое поле несколько раз, и таймер запускался только через 3 секунды после последнего нажатия клавиши. На это также намекают в документации, как вы увидите: вызов Timers.Start()просто устанавливает для Enabled значение true.

И, чтобы быть уверенным, к чему я должен был пойти прямо с самого начала, вы увидите в справочном источнике .NET, что при включении уже включенного таймера он вызывает частный UpdateTimer()метод, который вызывает внутренние вызовы Change().

NickSpag
источник
Нет, вы ошибаетесь. Частный UpdateTtimerметод вызывается тогда и только тогда, когда текущее значение Enabledне равно новому value.
Николо Карандини,
3

Для таймера (System.Windows.Forms.Timer).

Методы .Stop, затем .Start работали как сброс.

elmsoftware
источник
1

Другой альтернативный способ сбросить windows.timer - использовать счетчик, как показано ниже:

int tmrCtr = 0;
Timer mTimer;

private void ResetTimer()
{
  tmrCtr = 0;
}

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

Поэтому, если вы собираетесь повторять каждую 1 секунду, вы можете установить интервал таймера на 100 мс и проверить счетчик на 10 циклов.

Это подходит, если таймер должен ждать некоторых процессов, которые могут быть завершены в другой промежуток времени.

иван
источник
1

я сделаю это

//Restart the timer
queueTimer.Enabled = true;
Рисса
источник
Это просто позволяет. Даже если он был отключен заранее, повторное включение не меняет истекшее время, которое было собрано до этого момента.
vapcguy
1

Ты можешь сделать timer.Interval = timer.Interval

Элла Шаракански
источник