Нужно ли удалять System.Timers.Timer, если вы используете его в своем приложении?

Я использую класс System.Timers.Timer в одном из классов своего приложения. Я знаю, что у класса Timer есть метод Dispose, унаследованный от родительского класса Component, который реализует интерфейс IDisposable. Экземпляры указанного ниже класса создаются много раз в течение жизненного цикла моего приложения; у каждого из них есть экземпляр класса Timer, который непрерывно генерирует прошедшие события в течение жизненного цикла класса. Должен ли я реализовать интерфейс IDisposable в классе, который использует класс Timer для удаления объекта таймера? (Я видел код, который этого не делает). Боюсь, что некоторые неуправляемые ресурсы не будут освобождены, если я использую приведенный ниже класс следующим образом:

SomeClass someClass = new SomeClass();
someClass.DoSomething();
someClass = null;

Класс:

using System.Timers;

public class SomeClass
{
    private Timer m_timer;

    public SomeClass()
    {           
        m_timer = new Timer();
        m_timer.Interval = 1000;
        m_timer.Elapsed += new ElapsedEventHandler(m_timer_Elapsed);
        m_timer.AutoReset = false;
        m_timer.Start();                       
    }

    public void DoSomething()
    {

    }

    private void m_timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        try
        {
            //Do some task
        }
        catch (Exception ex)
        {
            //Ignore
        }
        finally
        {
            if (m_timer != null)
            {
                //Restart the timer
                m_timer.Enabled = true;
            }
        }
    }
}

person Roman Shumikhin    schedule 24.01.2009    source источник
comment
Хороший вопрос, к сожалению, пока нет реальных ответов ...!   -  person Pete Montgomery    schedule 16.05.2011


Ответы (7)


Вообще говоря, вы всегда должны избавляться от одноразовых ресурсов. Я, конечно, буду искать в случае, о котором вы говорите выше. Если вы реализуете IDisposable в классе, реализующем таймер, вы можете затем использовать класс в операторе using, что означает, что ресурсы будут явно освобождены при удалении вашего класса.

person flesh    schedule 24.01.2009

Я вижу, что вы задали этот вопрос год назад, но позвольте мне добавить свои 2 цента. Чуть меньше из-за инфляции :). Недавно я обнаружил в нашем приложении, что мы не избавлялись от таймеров. У нас была коллекция объектов, и у каждого объекта был таймер. Когда мы удалили элемент из коллекции, мы подумали, что это должен быть сборщик мусора. Почему-то не так с таймерами. Нам пришлось вызвать dispose для объекта в коллекции, чтобы избавиться от таймера до того, как объекты будут фактически собраны для сборки мусора.

person uriDium    schedule 21.05.2010
comment
Таймер поддерживается таймером Win32, который он создает под крышкой. Событие на таймере поддерживает ваш объект в живых. - person Ian Ringrose; 25.11.2010
comment
Обратите внимание, что System.Timers.Timer просто завершает вызов System.Threading.Timer и управляет объектом состояния (ссылка обратного вызова, используемая базовым api win32). - person Basic; 01.04.2016

Я использую практическое правило: создавать все, что имеет объект IDisposable, сам IDisposable (и удалять дочерние объекты только при явном вызове Dispose)

Есть хорошее обсуждение IDisposable в блоге Джо Даффи вместе с образцами кода, которые очень похожи на те, что в моей копии превосходного Книга" Рекомендации по созданию фреймворка "

person Rowland Shaw    schedule 24.01.2009
comment
Для тех, кто ищет запись в блоге Джо Даффи, ссылка на веб-архив. - person Korli; 21.12.2016
comment
@Korli обновили ссылку, чтобы указать на обновленную версию сообщения в блоге - person Rowland Shaw; 21.12.2016
comment
Спасибо, это гораздо актуальнее. К сожалению, разметка его блога на данный момент не работает. По крайней мере, для меня. - person Korli; 21.12.2016

Таймер необходимо утилизировать, иначе он будет продолжать работать еще некоторое время после того, как вы «закончите» с ним работать. Однако из-за проблем с потоками он может сработать через короткое время после того, как вы его удалили!

person Ian Ringrose    schedule 25.11.2010
comment
Что если вы сделаете timer.Change (Timeout.Infinite, Timeout.Infinite)? Не прекратит ли это срабатывание (хотя может поддерживать объект, который он вызывает через событие). - person Martin Capodici; 19.10.2015
comment
@MartinCapodici, возможно, он все еще начал следующее срабатывание, прежде чем ваш вызов timer.Change вернется. - person Ian Ringrose; 19.10.2015
comment
Ян, так что это звучит так же, как если бы вы избавились от него, в отношении другого возможного увольнения. Разница в том, что его удаление освободит объекты в памяти, хранимой событиями, тогда как простая остановка этого не сделает. - person Martin Capodici; 20.10.2015

Я бы предположил, что объект таймера создает или использует рабочий поток для запуска событий таймера. Вызов dispose освободит поток и связанные с ним ресурсы. Если это так, было бы неплохо вызвать dispose, чтобы неиспользуемые потоки не торчали слишком долго.

person 1800 INFORMATION    schedule 24.01.2009

Реализуя idisposable, вы сможете привести в порядок любые внутренние ресурсы, которые также реализуют idisposable, например, ваш таймер.

Кроме того, вы можете изменить свой код вызова, чтобы использовать статус using.

using (SomeClass someClass = new SomeClass())
{  
someClass.DoSomething();  
}  
person John    schedule 24.01.2009
comment
это почти придирка, но для ясности вам нужны круглые скобки вокруг оператора using: using (SomeClass someClass = new SomeClass ()) {...} - person Dave Cousineau; 26.07.2011
comment
Очень правильно, весь день прыгал между C # и VB. Ответ обновлен. Спасибо - person John; 26.07.2011

Я согласен с Роулендом.

В FxCop есть правило, которое находит классы, содержащие объекты Disposable, но не реализующие IDisposable должным образом.

person GregC    schedule 29.04.2009