Таймеры C# естественно многопоточные?
Если у меня есть два системных таймера, запускающих события в 10 и 20 секунд соответственно, являются ли вызовы функций событий многопоточными? В приведенном ниже сценарии у меня есть таймеры, которые запускают события с интервалами 10 и 12 соответственно. Ожидается, что функция My10sEvent будет вызвана первой. Если это медленная функция, выполнение которой занимает 8 секунд, заблокирует ли оно другое событие (tmr12s) или второе событие сработает по времени через 12 секунд?
System.Timers.Timer tmr10s = new System.Timers.Timer(10000.0);
tmr10s.Enabled = true;
tmr10s.Elapsed += new ElapsedEventHandler(My10sEvent);
System.Timers.Timer tmr12s = new System.Timers.Timer(12000.0);
tmr12s.Enabled = true;
tmr12s.Elapsed += new ElapsedEventHandler(My12sEvent);
Thread.Sleep(System.Threading.Timeout.Infinite); //sleep indefinitely to let the above events fire
3 ответа
CLR использует выделенный поток для отслеживания активных таймеров System.Timers.Timer и System.Threading.Timer. Событие Elapsed возникает в другом потоке, извлеченном из пула потоков.
Так что да, они продолжают тикать, не влияя друг на друга. Вы должны быть очень осторожны, вполне возможно, что ваш обработчик событий Elapsed будет вызван снова, пока он еще выполняется. Что происходит, когда это занимает больше времени, чем интервал. Или хуже, когда машина сильно загружена или у вас много активных потоков пула потоков. Это может очень трудно диагностировать сбой, если ваш обработчик событий не является поточно-ориентированным. Это почти никогда не бывает. Установка для свойства таймера AutoReset значения false - простой способ избежать этой проблемы.
Похоже, что он не будет блокироваться, если вы используете System.Threading.Timer или вызываете System.Timers.Timer без SynchronizingObject.
Подобный вопрос: таймеры C# истекают в отдельном потоке?
От System.Timers.Timer
документация:
Серверный таймер предназначен для использования с рабочими потоками в многопоточной среде. Таймеры сервера могут перемещаться между потоками для обработки инициированного события Elapsed, что приводит к большей точности, чем таймеры Windows, для своевременного инициирования события.
Так что да, это так.
Далее, от System.Timers.Timer.SynchronizingObject
документация по недвижимости:
Когда SynchronizingObject имеет значение null, метод, который обрабатывает событие Elapsed, вызывается в потоке из пула системных потоков. Для получения дополнительной информации о пулах системных потоков см. ThreadPool.
Таким образом, события генерируются в потоках пула потоков, если не установлен SynchronizingObject.