2012-06-26 3 views
2

Я разрабатываю приложение, которое запускает System.Threading.Timer, который делает довольно быстрое чтение/запись на последовательный порт (каждые 100 мс). Метод обратного вызова таймера выглядит примерно так: -.Net app thread/timer performance

if (_timerTaskRunning) 
{ 
    Debug.WriteLine("still running"); 
    return; 
} 

_timerTaskRunning = true; 

... do the serial write/read here ... 

_timerTaskRunning = false; 

Флаг _timerTaskRunning является гарантией для того, чтобы делегат не работает, если предыдущий таймер «цикл» еще не закончен, т.е. он занимает больше времени, чем 100мс ,

Когда я впервые запустил приложение, я вижу около десятка отладочных сообщений из инструкции if. Затем он опустится, но я увижу еще одну группу сообщений через 7 или 8 секунд. Он снова оседает, и время от времени я вижу, что группа сообщений появляется в разных количествах.

Я предполагаю, что первая группа сообщений вызвана тем, что делегат таймера работает медленно из-за запуска приложения, инициализации объектов/UI и т. Д. И т. Д., В то время как последующие сообщения, возможно, вызваны сбором мусора в каждом так часто и замедляет работу? Это не последовательный порт, потому что я вижу такое же поведение с «макетным» последовательным портом.

Я пробовал задерживать первый запуск таймера на пару секунд, но это не имеет значения. Я все еще получаю пакет отладочных сообщений в течение первой секунды или около того после запуска таймера. Это не конец света, который пропускает некоторые задачи таймера, но было бы интересно узнать, что может их вызвать. Есть ли что-нибудь, что я могу сделать, чтобы исследовать причину дальше, например. ли персмол пролить свет на вещи? Я не использовал его раньше, чем вы могли бы подсказать?

+0

Что вы здесь делаете? ... записывайте/читайте здесь ...?? –

+0

Ваш код чтения/записи может выполняться одновременно на двух отдельных потоках. –

+0

@thecoon да, вот где я пишу в последовательный порт, а затем читаю значение обратно. Как упоминалось в моем вопросе, это не последовательные сообщения, вызывающие провалы, поскольку я получаю такое же поведение, используя простой класс «макет». –

ответ

3

Похоже, что у вас проблема с повторной установкой. В основном ваш _timerTaskRunning не работает как гарантия, вероятно, из-за условий гонки.

  1. Использование System.Timers.Timer вместо System.Threading.Timer
  2. Set Timer.AutoReset ложь. Это устранит вашу захватывающую проблему, потому что она не перезвонит вам, пока вы ее явно не захотите.
  3. вызова Start() на ваш таймер, когда вам это нужно пойти еще раз (возможно, потребуется настроить интервал для учета времени выполнения)

Если у вас есть несколько потоков, которые могут позвонить начать вам нужно синхронизировать с ней вызовы.

+0

System.Timers.Timer, безусловно, приводит к созданию более чистого кода. Большое спасибо. –

2

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

Однако, я бы не использовал таймер вообще. Я внедрил неинтернетный таймер here. Он использует AutoResetEvent WaitOne с таймаутом, который обеспечивает повторное включение.