views:

2403

answers:

4

Does a System.Timers.Timer elapse on a separate thread than the thread that created it?

Lets say I have a class with a timer that fires every 5 seconds. When the timer fires, in the elapsed method, some object is modified. Lets say it takes a long time to modify this object, like 10 seconds. Is it possible that I will run into thread collisions in this scenario?

+7  A: 

MSDN Documentation on Timers states:

The System.Threading.Timer class makes callbacks on a ThreadPool thread and does not use the event model at all.

So indeed the timer elapses on a different thread.

Joren
True, but that is a completely different class. The OP asked about the System.Timers.Timer class.
Brian Gideon
Oh, you're right. http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx says "The Elapsed event is raised on a ThreadPool thread." Same conclusion from there I suppose.
Joren
Well, yeah, but it is not quite that simple. See my answer.
Brian Gideon
A: 

Each elapsed event will fire in the same thread unless a previous Elapsed is still running.

So it handles the collision for you

try putting this in a console

    static void Main(string[] args)
    {
        Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
        var timer = new Timer(1000);
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        Console.ReadLine();
    }

    static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        Thread.Sleep(2000);
        Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
    }

you will get something like this

10 6 12 6 12

where 10 is the calling thread and 6 and 12 are firing from the bg elapsed event. If you remove the Thread.Sleep(2000); you will get something like this

10 6 6 6 6

Since there are no collisions.

But this still leaves u with a problem. if u are firing the event every 5 seconds and it takes 10 seconds to edit u need some locking to skip some edits.

Simon
+12  A: 

It depends. The System.Timers.Timer has two modes of operation.

If SynchronizingObject is set to an ISynchronizeInvoke instance then the Elapsed event will execute on the thread hosting the synchronizing object. Usually these ISynchronizeInvoke instances are none other than plain old Control and Form instances that we are all familiar with. So in that case the Elapsed event is invoked on the UI thread and it behaves similar to the System.Windows.Forms.Timer. Otherwise, it really depends on the specific ISynchronizeInvoke instance that was used.

If SynchronizingObject is null then the Elapsed event is invoked on a ThreadPool thread and it behaves similar to the System.Threading.Timer.

Brian Gideon
A: 

If the elapsed event takes longer then the interval, it will create another thread to raise the elapsed event. But there is a workaround for this

static void timer_Elapsed(object sender, ElapsedEventArgs e)    
{     
   try
   {
      timer.Stop(); 
      Thread.Sleep(2000);        
      Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);    
   }
   finally
   {
     timer.Start();
   }
}
Rajan