Click here to Skip to main content
14,454,912 members
Rate this:
Please Sign up or sign in to vote.
See more:
public class Program
    {
        
        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);
        }
    }


What I have tried:

Hi all, 
Please see example below. Even though the reference to obj is set to null, the obj is not released and Obj_Elapsed continues printing i. Notice there is no reference to the timer out of the scope of the ObjectWithTimer constructor.
Posted
Updated 14-Feb-20 0:55am
Rate this:
Please Sign up or sign in to vote.

Solution 1

Variables aren't the same thing as the instance they contain: just setting a variable to null doesn't change the object it used to "point to", and it doesn't in any way mean that the system will immediately destroy (or even begin the process of destroying) the object itself.

Think of it in terms of cars: you own a car. You put your mobile in the glove box and sell the car. The new owner drives off into the sunset in his new car.
Where is your mobile?

You sold the car: you set the "pointer" "my car" to null - but that doesn't change the car itself in any way! It still drives, it still needs fuel, it still has your mobile in the glove box. Just you can't access the car, it's glove box, or your mobile any more because you discarded the only reference you had to it.

When you set up a timer it runs until all references to it are gone, and the system gets so low on memory that the Garbage Collector is kicked into action to decide what to dispose.
You want to stop the timer? Do just that:
Console.WriteLine("obj=null");
obj.t.Enabled = false;
obj = null;
Console.ReadLine();
   
Comments
phil.o 11-Feb-20 17:00pm
   
What happened to the jacket and the pen? :)
OriginalGriff 11-Feb-20 17:05pm
   
This is a shirt of a different colour! ;)
Rate this:
Please Sign up or sign in to vote.

Solution 2

If your class uses an object that implements IDisposable, as the Timer does, you should implement IDisposable in your class. You can then place your class within the confines of a using statement so that Dispose gets called when it goes out of scope and when an exception is thrown. Also, you will not be allowed to reassign the class instance within a using block and your error will be flagged up by the compiler.


static async Task Main()
       {

           {
               using ObjectWithTimer owt = new ObjectWithTimer();
               Console.ReadLine();
           }
           Console.WriteLine("Exited using's scope. Timer disposed.");
           Console.ReadLine();
       }
public sealed  class ObjectWithTimer : IDisposable
   {
       private int i;
       public Timer timer;
       public ObjectWithTimer()
       {
           timer = new Timer(2000);
           timer.Elapsed += TimerElapsed;
           timer.Enabled = true;
       }

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

       public void Dispose()
       {

           timer.Dispose();

       }
   }
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month



CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100