Может ли объект, содержащий активный таймер (System.Timers.Timer
), быть сборщиком мусора, если на него не ссылается никакой другой объект?
Объект Timer получает GC-ed, когда на него не ссылается другой объект?
Ответы (2)
Есть два основных способа, которыми Timer остается ссылкой, даже если вы где-то не храните ссылку:
Пока таймер включен. Существует базовый System.Threading.Timer, который фактически генерирует событие. CLR хранит список активных таймеров, их объект делегата обратного вызова сохраняет ссылку на Timer.
Обработчиком событий Elapsed, если он не является статическим. Это продлевает время жизни экземпляра Timer по крайней мере до времени жизни объекта класса, содержащего обработчик события Elapsed.
Здесь нет режима отказа. Единственный возможный способ получить ссылку на таймер — через аргумент sender обработчика Elapsed события. Если вы отключите таймер, больше не будет способа получить ссылку, поэтому он подходит для сбора объекта.
Довольно классический способ получить проблемы с этим таймером и потерять прошедшие события — это когда у вас есть свойство AutoReset, установленное в false. Очень неприятная проблема заключается в том, что любые исключения, возникающие в обработчике событий Elapsed, проглатываются без какой-либо диагностики. Что позволит обойти вызов, который вам придется перезапустить таймер в конце. Отдавайте предпочтение System.Threading.Timer, у него нет этой проблемы.
System.Threading.Timer
без ссылки может быть GC'ed, но не System.Timers.Timer
?
- person Stephen Cleary; 10.02.2011
System.Threading.Timer
без ссылок проходит GCed, а мой System.Timers.Timer
без ссылок с автоматическим сбросом - нет. Обработчик событий не ссылается на таймер. Можешь подтвердить? (Клиент .NET 4.0)
- person Stephen Cleary; 10.02.2011
System.Threading.Timer
, который представляет собой реализацию таймера, в которой вы должны явно сохранить ссылку на правило таймера, чтобы предотвратить его GC. Он просто меняет одну ловушку, в которую легко попасть, на другую. :(
- person Peter Duniho; 12.10.2019
да. Timer
будет GC'ирован, если не ссылаться на него, даже во время работы.
В документации говорится:
Код содержит объявления переменной таймера на уровне класса и внутри Main. Чтобы увидеть, как агрессивная сборка мусора может повлиять на таймер, объявленный внутри долго выполняющегося метода, вы можете закомментировать объявление уровня класса и раскомментировать локальную переменную. Чтобы таймер не собирался, раскомментируйте метод GC.KeepAlive в конце Main.