Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Timer is not working in cross threads

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?

like image 734
Shaharyar Avatar asked Jun 21 '13 21:06

Shaharyar


People also ask

Does timer run on main thread?

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.

Does system timers timer run in a separate thread?

Timers. Timer raises the elapsed event, is it raised in an independent thread? Yes, they run in a different thread. The System.

Is system threading timer thread-safe?

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.

Does timer create a new thread?

No, a timer runs in the thread in which it was created.


1 Answers

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.

like image 51
Hans Passant Avatar answered Sep 20 '22 20:09

Hans Passant