Подтвердить что ты не робот

Насколько масштабируемым является System.Threading.Timer?

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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