Объект не выпущен без ссылки на таймер Framework 4.8

Пожалуйста, смотрите пример ниже. Даже если ссылка на obj установлена ​​в null, obj не освобождается и Obj_Elapsed продолжает печатать i. Обратите внимание, что нет ссылки на таймер вне области видимости конструктора ObjectWithTimer.

общественная программа

    public static void Main(string[] args)
    {
        object obj = new ObjectWithTimer();
        Console.ReadLine();
        Console.WriteLine("obj=null");
        obj = null;
        Console.ReadLine();
    }
}

public class ObjectWithTimer
{
    private int i;
    public System.Timers.Timer t;
    public ObjectWithTimer()
    {
        t = new System.Timers.Timer(5000);
        t.Elapsed += Obj_Elapsed;
        t.Enabled = true;
    }

    public void Obj_Elapsed(object sender, ElapsedEventArgs e)
    {
        i++;
        Console.WriteLine(i);
    }
}

Всего 1 ответ


Установка null в этом случае и / или выход из области не достаточно хорош, у Timer есть ресурсы, Timer он управляет, и его необходимо очистить.

Поскольку System.Timers.Timer IDisposable , в идеале так же должен быть класс- оболочка

public class ObjectWithTimer : IDisposable
{
   // Flag: Has Dispose already been called?
   private bool _disposed = false;

   private int _i;
   public System.Timers.Timer Timer { get; }
   public ObjectWithTimer()
   {
      Timer = new System.Timers.Timer(5000);
      Timer.Elapsed += Obj_Elapsed;
      Timer.Enabled = true;
   }

   public void Obj_Elapsed(object sender, ElapsedEventArgs e)
   {
      _i++;
      Console.WriteLine(_i);
   }

   // Public implementation of Dispose pattern callable by consumers.
   public void Dispose() =>Dispose(true);


   // Protected implementation of Dispose pattern.
   protected virtual void Dispose(bool disposing)
   {
      if (_disposed) return; 
      if (disposing) Timer?.Dispose();  
      _disposed = true;
   }
}

Затем вы должны также избавиться от обертки, вызываемой на каком-то этапе, а не просто установить ее в ноль , самый простой способ сделать это с помощью оператора using

Предоставляет удобный синтаксис, который обеспечивает правильное использование IDisposable объектов.

public static void Main(string[] args)
{
    using(object obj = new ObjectWithTimer())
    {
       Console.ReadLine();
       Console.WriteLine("obj=null");
    }
    Console.ReadLine();
}

Реализация метода Dispose

Вы реализуете метод Dispose для освобождения неуправляемых ресурсов, используемых вашим приложением. Сборщик мусора .NET не выделяет и не освобождает неуправляемую память.

Примечание . Это был не полный учебник по шаблону IDisposable , а просто пример. Пожалуйста, сделайте свое собственное исследование и усердие в этой реализации


Дополнительные Ресурсы


Есть идеи?

10000