Насколько масштабируема система.Многопоточность.Таймер?

StackOverflow https://stackoverflow.com/questions/31581

  •  09-06-2019
  •  | 
  •  

Вопрос

Я пишу приложение, в котором нужно будет использовать Timers, но потенциально их очень много.Насколько масштабируема система System.Threading.Timer класс?В документации просто говорится, что она "легкая", но ничего больше не объясняется.Засасываются ли эти таймеры в один поток (или очень маленький threadpool), который обрабатывает все обратные вызовы от имени Timer, или же каждый Timer есть свой собственный поток?

Я думаю, что другой способ перефразировать вопрос таков:Как это System.Threading.Timer реализовано?

Это было полезно?

Решение

Я говорю это в ответ на множество вопросов:Не забывайте, что (управляемый) исходный код фреймворка доступен.Вы можете использовать этот инструмент, чтобы получить все это: http://www.codeplex.com/NetMassDownloader

К сожалению, в данном конкретном случае большая часть реализации находится в машинном коде, так что вы не сможете на это взглянуть...

Однако они определенно используют потоки пула, а не поток на таймер.

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

Грубо говоря, это дает O (log n) для запуска таймера и O (1) для обработки запущенных таймеров.

Редактировать:Только что заглянул в книгу Джеффа Рихтера.Он говорит (о потоковой обработке.Timer), что он использует один поток для всех объектов Timer, этот поток знает, когда наступит следующий таймер (т.е.как указано выше) выполняется и вызывает ThreadPool.QueueUserWorkItem для обратных вызовов по мере необходимости.Это приводит к тому, что если вы не завершите обслуживание одного обратного вызова по таймеру до наступления следующего, ваш обратный вызов будет повторно выполнен в другом потоке пула.Итак, подводя итог, я сомневаюсь, что вы увидите большую проблему с большим количеством таймеров, но вы можете столкнуться с истощением пула потоков, если большое количество из них запускается с одним и тем же таймером и / или их обратные вызовы выполняются медленно.

Другие советы

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

Вот хорошая статья из журнала MSDN, опубликованная несколько лет назад, в которой сравниваются три доступных класса таймеров и дается некоторое представление об их реализации:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

Объедините их.Создайте службу таймера и запросите ее для таймеров.Для этого нужно будет поддерживать активным только 1 таймер (для следующего вызова)...

Чтобы это было улучшением по сравнению с простым созданием большого количества объектов Threading.Timer, вы должны предположить, что это не совсем то, что Threading.Timer уже выполняет внутренне.Мне было бы интересно узнать, как вы пришли к такому выводу (я не разобрал исходные части фреймворка, так что вы вполне можете быть правы).

^^ как говорит ДэнниСмерф :Объедините их.Создайте службу таймера и запросите ее для таймеров.Потребуется сохранить только 1 активный таймер (для следующего своевременного вызова) и историю всех запросов таймера и пересчитать это в AddTimer() / RemoveTimer().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top