I have 2 global System.Windows.Forms.Timer
in my form. Both are initialized in form's constructor. But not started yet. Constructor starts a new thread and that thread enables and starts both of the timers. Obviously it is all cross threading, but it doesn't throw any cross-thread exception. But it doesn't even work. It does not fire the Timer.Tick
method. Here is the code:
1st Method:
In form constructor:
KeepMeAliveTimer = new Timer(); //timer 1
KeepMeAliveTimer.Interval = 15000;
KeepMeAliveTimer.Tick += KeepMeAlive;
timer1 = new Timer(); //timer 2
timer1.Interval = 15000;
timer1.Tick += timer1_Tick;
//started a new thread
In new thead:
//after performing some tasks, it enables the timers
KeepMeAliveTimer.Enabled = true; //timer 1
KeepMeAliveTimer.Start();
timer1.Enabled = true; //timer 2
timer1.Start();
But it is not firing up Timer's tick events and not even throwing any exception.
2nd Method:
But when I initialized and enabled the Timers
in the same thread (Main Thread) they are working perfectly:
KeepMeAliveTimer = new Timer(); //timer 1
KeepMeAliveTimer.Interval = 15000;
KeepMeAliveTimer.Tick += KeepMeAlive;
KeepMeAliveTimer.Enabled = true;
KeepMeAliveTimer.Start();
timer1 = new Timer(); //timer 2
timer1.Interval = 15000;
timer1.Tick += timer1_Tick;
timer1.Enabled = true;
timer1.Start();
Now the question is; Why the first method is not working if there is not even any exception?
If a timer is fired on the main thread's run loop, you will probably have a problem with either the timer function or UI operation. For example, suppose you have triggered a timer. There is also a tableView in your app that shows a list to the user and the user is scrolling the table.
Timers. Timer raises the elapsed event, is it raised in an independent thread? Yes, they run in a different thread. The System.
Timer is not thread-safe. Since then this has been repeated on blogs, in Richter's book "CLR via C#", on SO, but this is never justified.
No, a timer runs in the thread in which it was created.
The Timer class is thread-safe but not in the way you expect it. Calling the Start() method on worker thread does actually start the timer. The class goes through the effort of creating a hidden window so it can call the SetTimer winapi function and receive the WM_TIMER message when it is done.
But the Tick event cannot be raised if nobody is listening for that message. You won't be, surely you didn't call Application.Run() on that thread. You should therefore not start a timer on a worker thread. Use Control.BeginInvoke if necessary to get it started on the UI thread.
Or use a System.Threading.Timer or System.Timers.Timer, they don't depend on a message loop. You do have to interlock properly, their Elapsed event or callback run on yet another thread. Which is the kind of solution that tends to create another problem.
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