whytheq
whytheq

Reputation: 35557

Garbage Collection - is it required?

In general it's good practice to garbage collect as it frees up resources. How do I implement correct garbage collection in the following code's keepingTime method? Or, in fact, do I even need to?!

System.Timers.Timer allows IDisposable interface so 'using' is an option, but not in the following as the scope of the timer needs to extend to the method myTimer_Elapsed that is subscribed to the Timer Elapsed event. I've made two attempts to garbage collect but both fail as the timer does not then hang around long enough!

I've previously dicussed this code, for other reasons, in HERE

public partial class AirportParking : Form
{

    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //instance variables of the form
    System.Timers.Timer myTimer;

    private const string EvenText = "hello";
    private const string OddText = "hello world";

    static int tickLength = 100; 
    static int elapsedCounter;
    private int MaxTime = 5000;
    private TimeSpan elapsedTime; 
    private readonly DateTime startTime = DateTime.Now; 
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


    public AirportParking()
    {
        InitializeComponent();
        lblValue.Text = EvenText;
        keepingTime();
    }

    //method for keeping time
    public void keepingTime() {

        myTimer = new System.Timers.Timer(tickLength);
        myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        myTimer.AutoReset = true;
        myTimer.Enabled = true;
        myTimer.Start();

        //ATTEMPT_1.tried the following unsuccessfully
        //using (System.Timers.Timer myTimer = new System.Timers.Timer(tickLength))
        //{
        //    myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        //    myTimer.AutoReset = true;
        //    myTimer.Enabled = true;
        //    myTimer.Start();
        //}

        //ATTEMPT_2.tried the following unsuccessfully
        //myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed);
        //myTimer.AutoReset = true;
        //myTimer.Enabled = true;           
        //try
        //{
        //    myTimer.Start();
        //}
        //finally
        //{
        //    myTimer.Dispose();
        //}

    }

    private void myTimer_Elapsed(Object myObject,EventArgs myEventArgs){

        elapsedCounter++;
        elapsedTime = DateTime.Now.Subtract(startTime);

        if (elapsedTime.TotalMilliseconds < MaxTime)
        {
            this.BeginInvoke(new MethodInvoker(delegate
            {
                this.lblElapsedTime.Text = elapsedTime.ToString();

                if (elapsedCounter % 2 == 0)
                    this.lblValue.Text = EvenText;
                else
                    this.lblValue.Text = OddText;
            }));
        }
        else {myTimer.Stop();}
    }
}

Upvotes: 0

Views: 181

Answers (3)

Marchief
Marchief

Reputation: 11

Although it is good practice to garbage collect, in this instance it would be would be done automatically when you close the form or the instance dies.

The only time I really worry about this is with SQL readers as you have to make sure they are closed off when you are finished otherwise it causes all sorts of problems.

Upvotes: 1

yamen
yamen

Reputation: 15618

The only place you'll want to dispose of the timer resource is in the callback function myTimer_Elapsed. Where you do myTime.Stop(); you can also do myTimer.Dispose();.

However, when this part of the application goes out of scope, all these variables will be cleaned up anyway. As long as the timer is eventually stopped, once it's dereferenced it will be collected by the GC.

The reason the using blocks (and your current Dispose()) doesn't work is that you're throwing away the timer as soon as you create it! You have to let it run in the background.

Upvotes: 2

Tigran
Tigran

Reputation: 62246

Dispose your timer on Form's OnClosing event, if this is not a main form, or by the way, a Form that always visible.

A pseudocode can look like this:

public partial class AirportParking : Form
{
  .....
  .....

  protected override void OnClosing(...)
  {
       myTimer.Dispose();
  }
}

If this is some "long-running" form, you should add disposal of the timere at the moment you no more need it, but I think you already know that.

Upvotes: 2

Related Questions