timer.enabled and garbage collection
I was checking out the help on the Timer.Stop method, and the remarks said this:
Quote:
You can also stop the timer by setting the Enabled property to false. A timer that is disabled is subject to garbage collection.
does this mean that it is possible for you to disable a timer, then when you try to enable it again, the timer object is no longer available? Being used to the VB6 timer, I would have used the .enabled property to set this without thinking twice, but by dumb chance I read that and changed it to .stop.
It seems to me, that setting the timer.enabled to false (then back to true some time later) is essentially the same as setting the timer to null (Then creating a new instance some time later) - and in fact the second would be better because it will always work, while if you set it to false, it may work sometimes, but not others (depending on when garbage collection runs).
Are my fears correct? Of course, now I know to use the timer.stop/start method, but it seems strange that setting enabled to false then mean GC will dispose of it. If i disable a text box it won't do that.
Re: timer.enabled and garbage collection
yeah,exactly
when you set it to false its marked for GC,so it could free the resources held by the timer
and this a bit differs from a textbox!
this timer uses UI messages for executing the intervals,better timer is System.Threading.Timer
if you look at it,you see when we don't have any work with timers we call its dispose method
Re: timer.enabled and garbage collection
I would assume that, as long as you have a reference to the timer it won't be garbage collected.
A timer without any references, that still is enabled, can not be garbage collected.
Code:
private void button_Click(object sender, System.EventArgs e)
{
Timer myTimer=new Timer();
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Interval = 5000;
myTimer.Start();
}
private void myTimer_Tick(object sender, EventArgs e)
{
DialogResult rslt=MessageBox.Show(
this,"Stop timer?","Timer elapsed",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (rslt==DialogResult.Yes)
{
Timer myTimer=(Timer)sender;
myTimer.Stop();
}
}
In the above example, there are no references to the timer, so when stop is called, the timer can be garbage collected.
Re: timer.enabled and garbage collection
I am not a specialist, but maybe it means that when the timer is set to false, the windows-timer internally stored in the C# timer object, is freed, and reallocated if the timer is set to true.
Re: timer.enabled and garbage collection
klintan,why in the above example there is no refernce?
Code:
Timer myTimer=(Timer)sender;
myTimer is the handle and there is a refernce from the handle to the sender
Re: timer.enabled and garbage collection
this is MSDN example but it's not going to be garbage collected except when its dispose method is called
Code:
using System;
using System.Threading;
class TimerExampleState
{
public int counter = 0;
public Timer tmr;
}
class App
{
public static void Main()
{
TimerExampleState s = new TimerExampleState();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate = new TimerCallback(CheckStatus);
// Create a timer that waits one second, then invokes every second.
Timer timer = new Timer(timerDelegate, s,1000, 1000);
// Keep a handle to the timer, so it can be disposed.
s.tmr = timer;
// The main thread does nothing until the timer is disposed.
while(s.tmr != null)
Thread.Sleep(0);
Console.WriteLine("Timer example done.");
}
// The following method is called by the timer's delegate.
static void CheckStatus(Object state)
{
TimerExampleState s =(TimerExampleState)state;
s.counter++;
Console.WriteLine("{0} Checking Status {1}.",DateTime.Now.TimeOfDay, s.counter);
if(s.counter == 5)
{
// Shorten the period. Wait 10 seconds to restart the timer.
(s.tmr).Change(10000,100);
Console.WriteLine("changed...");
}
if(s.counter == 10)
{
Console.WriteLine("disposing of timer...");
s.tmr.Dispose();
s.tmr = null;
}
}
}
Re: timer.enabled and garbage collection
Quote:
Originally Posted by mehdi62b
klintan,why in the above example there is no refernce?
When the method goes out of scope there is no longer a reference to it and the timer may be garbage collected.
With System.Threading.Timer, a reference must be kept even when the timer is running, since it otherwise might get garbage collected and thus never will expire.
A System.Windows.Forms.Timer, will not be garbage collected as long as it is enabled.
Re: timer.enabled and garbage collection
I think you guys missed the key point mentioned by
Quote:
Originally Posted by mehdi62b
yeah,exactly
when you set it to false its marked for GC,so it could free the resources held by the timer
10 points to Mehdi.
Re: timer.enabled and garbage collection
Quote:
Originally Posted by Andy Tacker
I think you guys missed the key point mentioned by
Quote:
Originally Posted by mehdi62b
yeah,exactly
when you set it to false its marked for GC,so it could free the resources held by the timer
10 points to Mehdi.
So you guys are saying that with Windows.Forms.Timers one must code like this:
Code:
private System.Windows.Forms.Timer timer1;
private void InitializeComponent()
{
// Designer generated code, timer.Enabled=false when created
this.timer1 = new System.Windows.Forms.Timer(this.components);
}
private void button1_Click(object sender, System.EventArgs e)
{
// Make sure timer not has been garbage collected
if (this.timer1==null)
{
this.timer1 = new System.Windows.Forms.Timer(this.components);
}
// Pray that garbage collection not happens here
this.timer1.... // do something with timer
}
I would assume that an object that I have a reference to never is garbage collected.
Re: timer.enabled and garbage collection
friends,
I told its marked for GC not immediately is collected and yeah its global..
Quote:
Originally Posted by klintan
When the method goes out of scope there is no longer a reference to it and the timer may be garbage collected.
I think this doesn't imply for all time,suppose the Tick event is something like below
Code:
public class Timer
{
public event EventHandler Tick;
protected virtual void OnTick(EventArgs e)
{
if (Tick != null)
{
//Invokes the delegates.
Tick(this, e);
}
}
}
when the delegate invoked you see we send this to the destination method(late binding),then when in the destination method we get it via sender I think it can't be garbage collected
Re: timer.enabled and garbage collection
Well, actually it can be garbage collected.
Make a form with two buttons, btnStartTimer and btnGC, and add the following code:
Code:
private WeakReference wr=null;
private void btnStartTimer_Click(object sender, System.EventArgs e)
{
Timer myTimer=new Timer();
myTimer.Tick += new EventHandler(myTimer_Tick);
myTimer.Interval = 10000;
myTimer.Start();
wr=new WeakReference(myTimer);
}
private void myTimer_Tick(object sender, EventArgs e)
{
DialogResult rslt=MessageBox.Show(this,"Stop timer?","Timer elapsed",MessageBoxButtons.YesNo,MessageBoxIcon.Question);
if (rslt==DialogResult.Yes)
{
Timer aTimer=(Timer)sender;
aTimer.Stop();
}
}
private void btnGC_Click(object sender, System.EventArgs e)
{
bool aliveBefore=wr.IsAlive;
GC.Collect();
bool aliveAfter=wr.IsAlive;
MessageBox.Show(String.Format("Alive before: {0}, Alive after: {1}",aliveBefore,aliveAfter));
}
Run the code, press the start timer button, then the GC button (timer is still alive).
When timer elapses, press No for stop timer, then the GC button (timer is still alive).
When timer elapses again, press Yes for stop timer, then the GC button (timer is no longer alive after GC).
Change the code so that myTimer is a private field of the form, then run as above again. Now timer will be alive, always.
Thus, as long as you have a reference to the timer in an active object the timer will never be garbage collected. If you don't have a reference to the timer, it won't get garbage collected as long as it is enabled. Which was exactly what I said in the beginning.
Any object on heap to which you have references to, indirectly or directly, from the stack, will never be garbage collected. Objects that you cannot refer to from stack, cannot longer be reach and may thus be garbage collected, with some exceptions like Windows.Forms.Timer. Even if these objects has references back to some object on stack, they can still be garbage collected. A good thing with .Net is that even if these objects has references to each other (circular references), they can still be garbage collected (I remember having problems with circular references in VB 6.0).
If you cannot be sure that an object that you have a reference to still exists, well you would get some very strange errors after your program has executed for a while. (As you all know, normally you never invoke GC directly like in my example above, and you never know when GC actually happens).
Re: timer.enabled and garbage collection
thanks for the explanatins and examples
it clearly shows all the possibilities ;)
Quote:
Originally Posted by klintan
Objects that you cannot refer to from stack, cannot longer be reach and may thus be garbage collected, with some exceptions like Windows.Forms.Timer.
yes exactly :)
I owe you 2 rates! :D
Re: timer.enabled and garbage collection
cheers guys. thanks for the feedback.
(must... spread... reputation....)
Re: timer.enabled and garbage collection
Read the fine print if you are using a Windows.Forms.Timer
"This instance will exist until its container releases it to garbage collection."
So if you use the public Timer(IContainer); constructor you don't have an issue with stopping the Timer and it being garbage collected.