2013-05-24 5 views
-2

У меня есть следующие сценарии, использующие System.Timers.Timer.Резьба внутри метода System.Timers.Timer

Создание объекта Timer и назначить метод

_JobListener.Enabled = false; 
_JobListener.Elapsed += (this.JobListener_Elapsed); 

В JobListener_Elapsed, я создал другой поток для выполнения некоторых функций.

JobListener_Elapsed 
{ 
    //stop the timer 
    _JobListener.Enabled = false; 

    System.Threading.Thread pollThread = new Thread(JobListener_ElapsedAsync); 
    pollThread.Start(); 

    //join to the main timer thread 
    pollThread.Join(); 

    //restart the timer 
    _JobListener.Enabled = true; 
} 

Внутри JobListener_ElapsedAsync я регистрирую статус включения таймера.

private void JobListener_ElapsedAsync() 
{ 
    try{ 
     log Timer.Enabled 
     some other code 
    }finally 
    { 
     _JobListener.Enabled = true; 
    } 
} 

Однако, я могу видеть несколько раз, он может видеть, что статус таймера является истинным, что неверно. Таймер должен быть остановлен при запуске JobListener_ElapsedAsync.

Любая идея?

+8

Какой смысл начинать новый поток, если поток, начинающийся с него, просто блокируется до тех пор, пока он не закончится? Вы можете просто запустить код непосредственно в обработчике событий, если вы это делаете. – Servy

+0

@Servy Я задавал себе тот же вопрос. Это какой-то старый код. Я исправил его, чтобы не использовать отдельный поток. Но я смущен этим поведением, когда сохраняю этот отдельный поток внутри метода Timer. – Helic

+1

Где в вашем коде вы когда-либо включали таймер? Он должен быть включен * где-то *. Этот код, вероятно, вызывается во время его запуска. У вас также может быть несколько обработчиков с истекшим сроком, вы можете просто наблюдать это неправильно, ваш метод async может запускать * другую операцию async, что приводит к тому, что текущий поток продолжает включать таймер и т. Д. Простым фактом является то, t показано достаточно кода, чтобы узнать, в чем проблема. – Servy

ответ

3

В .NET Framework есть два основных класса таймера: таймеры потоков и таймеры окон.

System.Threading.Timer является основным классом для таймеров потоков. Это обертывает Windows waitable timer object. Событие Tick запускается на ThreadPool. Он не проверить, не были ли все обработчики для предыдущего Tick вернулись перед запуском Tick. Таймер должен срабатывать вовремя - он не задерживается.

System.Windows.Forms.Timer обертывает Windows SetTimer API. Событие Tick запускается в потоке, который создает таймер. Если это не поток пользовательского интерфейса, он фактически не срабатывает. Таймеры являются сообщениями с наименьшим приоритетом; они генерируются только GetMessage/PeekMessage, когда другие сообщения не выдаются. Поэтому они могут быть значительно отсрочены, когда они должны быть сгенерированы.

System.Timers.Timer обертывания System.Threading.Timer. Если вы установили свой объект SynchronizingObject на что-то, когда срабатывает таймер, он будет использовать ISynchronizeInvoke.Invoke, чтобы попасть на нить этого объекта (аналогично Control.Invoke - действительно Control реализует ISynchronizeInvoke). Он блокирует поток пула потоков в этом процессе. Если SynchronizingObject is null, он просто запускает событие Elapsed в потоке пула потоков. Единственное реальное использование этого класса - если вам нужно, чтобы таймеры для компонентов пользовательского интерфейса были уволены вовремя. Если вам не нужно синхронизировать, вместо этого используйте System.Threading.Timer.

Если вам необходимо убедиться, что предыдущий Tick событие полностью обработано (все обработчики вернулись) до начала следующего один, вам нужно либо:

  • Сделать таймер один выстрел, а не периодический , и последний обработчик установить еще один выстрел, когда он заканчивает выполняющийся
  • используйте lock или Monitor для предотвращения двух потоков, поступающих в обработчик (но вы можете использовать все потоки в пуле потоков)
  • Использование Monitor.TryEnter для только ввести обработчик, если предыдущий o ne закончил (но вы могли пропустить некоторые Tick s).
+0

, можете ли вы объяснить немного больше о решениях, чтобы полностью обработать предыдущее событие Tick? Благодарю. – Helic

Смежные вопросы