I'm doing a small test project before I use System.Threading.Timer
in a Windows Service project. It's working wonderfully, however the timer stops on its own after a minute or two.
The full source for the test project is:
using System; using System.Windows.Forms; using System.Threading; namespace studyTimers { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { TimerCallback timerDelegate = new TimerCallback(tick); System.Threading.Timer testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000); } void tick(Object obj) { if (label1.InvokeRequired) { label1.Invoke(new MethodInvoker(() => tick(obj))); } else { label1.Text = DateTime.Now.ToString(); } } } }
The goal is obviously to update a label with the current time. I am noticing that updating stops after a bit. Why would this be?
The application thread creates the timer, which waits one second and then executes the CheckStatus callback method every 250 milliseconds. The application thread then blocks until the AutoResetEvent object is signaled. When the CheckStatus callback method executes maxCount times, it calls the AutoResetEvent.
Timer raises the elapsed event, is it raised in an independent thread? Yes, they run in a different thread.
Timer is not thread-safe.
To end or quit the timer, one must use a cancel() function. Importing the threading class is necessary for one to use the threading class. The calling thread can be suspended for seconds using the function time. sleep(secs).
If you need a timer on a Windows Form then drop a System.Windows.Forms.Timer
onto the form - there's no reason to use a System.Threading.Timer
unless you need better resolution than 55 ms.
The reason the timer "stops" is because it's being garbage-collected. You're allowing it to go out of scope in the Form1_Load
method because you only declare it as a local variable. In order to keep the timer "alive", it needs to be a private field on the form class so that the GC knows it's still needed.
In other words:
public partial class Form1 : Form { private System.Threading.Timer testTimer; ... public void Form1_Load(object sender, EventArgs e) { TimerCallback timerDelegate = new TimerCallback(tick); testTimer = new System.Threading.Timer(timerDelegate, null, 1000, 1000); } }
But again, in this case it's simplier to use System.Windows.Forms.Timer
, which is an actual component in the toolbox that you can just drop onto the form.
Edit - As the comments now reveal, if this is just a test app and the real application is in a Windows Service, you cannot use System.Windows.Forms.Timer
for that. Just remember not to let your System.Threading.Timer
go out of scope.
Garbage collector collected the timer object, you should keep a reference to it. this post will help: http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With