Получает ли объект Timer GC-ed, когда никакой другой объект не ссылается на него? - PullRequest
6 голосов
/ 10 февраля 2011

Может ли объект, содержащий активный таймер (System.Timers.Timer), быть собранным мусором, если никакой другой объект не ссылается на него?

Ответы [ 2 ]

10 голосов
/ 10 февраля 2011

Существует два основных способа ссылки на таймер, даже если вы не храните ссылку где-либо:

  • Пока таймер включен. Существует базовый System.Threading.Timer, который фактически генерирует событие. CLR хранит список активных таймеров, объект делегата обратного вызова сохраняет ссылки на Timer.

  • Обработчиком событий Elapsed, если он не является статическим. Это продлевает время жизни экземпляра Timer как минимум до времени жизни объекта класса, который содержит обработчик Elapsed.

Здесь нет режима отказа. Единственный возможный способ вернуть ссылку на таймер - использовать аргумент обработчика событий Elapsed sender . Если вы отключите таймер, то больше не будет способа получить ссылку, поэтому он подходит для собираемого объекта.

Довольно классический способ попасть в неприятности с этим Таймером и потерять события Elapsed - это когда для свойства AutoReset установлено значение false. Очень неприятная проблема заключается в том, что любые исключения, возникающие в обработчике событий Elapsed, проглатываются без какой-либо диагностики. Который будет обходить вызов вам придется перезапустить таймер в конце. Поддержите System.Threading.Timer, у него нет этой проблемы.

1 голос
/ 10 февраля 2011

Да. Timer будет GC'd, если оставить без ссылки, даже во время работы.

Документация гласит:

Код содержит объявления переменной таймера на уровне класса и внутри Main. Чтобы увидеть, как агрессивная сборка мусора может влиять на таймер, который объявлен внутри долгосрочного метода, вы можете закомментировать объявление уровня класса и раскомментировать локальную переменную. Чтобы таймер не собирался, раскомментируйте метод GC.KeepAlive в конце Main.

...