Як скинути таймер у C #?


114

Є три Timerкласу , які я знаю, System.Threading.Timer, System.Timers.Timerі System.Windows.Forms.Timer, але жоден з них не має .Reset()функції , яка буде скинути поточний час , що минув до 0.

Чи існує клас BCL, який має цю функціональність? Чи існує такий спосіб, як це зробити? (Я думав, можливо зміна обмеження часу може скинути його) Думав про те, як важко буде повторно реалізувати Timerклас, який має цю функціональність, або як надійно це зробити з одним із класів BCL?


3
Використовуючи рішення JP, використовуйте метод розширення
benPearce

У мене теж є така ж потреба в скидці і з тих же причин, згаданих, FileSystemWatcher неприємний і незручний у використанні
Джон Левін

Якщо ви використовуєте Секундомір для таймера і переходите з відповіддю методу розширення, будьте обережні, оскільки в .NET 4.0 надходить метод розширення Stopwatch.Restart. msdn.microsoft.com/en-us/library/…
si618

Відповіді:


148

Я завжди так ...

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

... це хак? :)

За коментарем, на Threading.Timer, це метод Змінити ...

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


Інша проблема полягає в тому, що тільки неприємності з 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 переглядає каталог і хочу вловлювати групи змін (тобто зміни, внесені, наприклад, 5s один з одного). Теорія полягає в тому, що перша зміна запускає таймер, який обнуляється з кожною зміною, поки в кінцевому підсумку не запускається і закривається з групи.
Меттью Шарлі

Так, я помітив це, коли перечитав ваше запитання. Відредагував мою відповідь.
День

Це працює, і важливо зазначити, що це не працюватиме, якщо ви лише дзвоните timer.Start(). Я зробив цей запит Linqpad, щоб перевірити його. Спробуйте видалити timer.Stopйого, і ви побачите різницю.
Пляж Джаред

30

Бо System.Timers.Timer, згідно з документацією MSDN, http://msdn.microsoft.com/en-us/library/system.timers.timer.enabled.aspx :

Якщо інтервал встановлений після запуску таймера, кількість відновлюється. Наприклад, якщо встановити інтервал в 5 секунд, а потім встановити властивість Enabled на істинне, підрахунок починається з моменту встановлення 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 В ОП чітко зазначено " a .Reset () функція, яка б скинула поточний минулий час до 0. " - не йдеться про те, що він призначений для використання в погано розробленому додатку, де ви навіть не знаєте, чи працює таймер. Також перевірте коментар автора (більше 4 років тому): " Теорія полягає в тому, що перша зміна запускає таймер, який змінюється з кожною зміною, поки в кінцевому підсумку не запускається і не закривається з групи. " Дякуємо за прихильний голос.
mMontu

Я також бачив подібну проблему. Що я зробив: aTimer.Interval = aTimer.Interval. Це спричинило, що цикл триває. Бій мене чому, але це працює ...
Герман Ван Дер Блом

7

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

  • дзвінки Зупинити () - Почати () для Timers.Timer та Forms.Timer
  • дзвінки Змінити для теми

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
    }

5

Для ясності, оскільки деякі інші коментарі є невірними, якщо використовувати System.Timersпараметр Включено до істинного, буде скинуто минулий час. Я просто перевірив поведінку нижче:

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 на істинний.

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


Ні, ти не прав. Приватний UpdateTtimerметод називається тоді і тільки тоді, коли поточне значення Enabledне дорівнює новому value.
Ніколо Карандіні


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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.