Do System.Timers.Timer run in independent Threads?

24,949

Solution 1

According to the MSDN, on System.Timers.Timer when the Elapsed event fires it is called on a thread in the system thread-pool:

If the SynchronizingObject property is Nothing, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.

Since the default value of SynchronizingObject is null, then all your elapsed events would be handled on the thread pool. So, it depends how full the thread pool is, if there are free threads, then each elapsed event can most likely run concurrently on separate threads. If for some reason, though, the system thread-pool is already fully in use, it's possible the elapsed events could be serialized as they are scheduled.

The main point is: "it depends." That is, they will be allowed to run in parallel as long as there are free threads in the pool.

Reference: MSDN on System.Timers.Timer

Solution 2

Based on your code they must be, since Thread.Sleep is a blocking call. None of the other timers would fire if they were running on the same thread.

You could output System.Threading.Thread.CurrentThread.ManagedThreadId in each one to know for sure.

Solution 3

It's quite complex. The documentation says the following:

The server-based Timer is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event, resulting in more accuracy than Windows timers in raising the event on time.

and then this:

If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread. If processing of the Elapsed event lasts longer than Interval, the event might be raised again on another ThreadPool thread. In this situation, the event handler should be reentrant.

and then this:

If you use the Timer with a user interface element, such as a form or control, without placing the timer on that user interface element, assign the form or control that contains the Timer to the SynchronizingObject property, so that the event is marshaled to the user interface thread.

So, there's no simple answer to your question "is it raised in an independent thread?" It depends on many things.

Solution 4

Yes, each time Elapsed is called, the callback is fired on its own thread.

In addition, there is nothing stopping one Elapsed event handler from firing before the previous one is completed. For instance, if your timer fires every 500 milliseconds, but the Elapsed event handler code takes 2 seconds to complete, the Elapsed code can be accessing the same resources (non thread-safe objects, files, etc).

Share:
24,949
newbie
Author by

newbie

Updated on July 09, 2022

Comments

  • newbie
    newbie almost 2 years

    I'm trying to understand when the System.Timers.Timer raises the elapsed event, is it raised in an independent thread?

    My example below seems to suggest that the three timers run independently in their own threads:

    class Program
    {
        static System.Timers.Timer timer = new System.Timers.Timer();
        static System.Timers.Timer timer2 = new System.Timers.Timer();
        static System.Timers.Timer timer3 = new System.Timers.Timer();
    
        static void Main(string[] args)
        {
            timer.Elapsed += new System.Timers.ElapsedEventHandler(
                timer_Elapsed);
            timer2.Elapsed += new System.Timers.ElapsedEventHandler(
                timer2_Elapsed);
            timer3.Elapsed += new System.Timers.ElapsedEventHandler(
                timer3_Elapsed);
    
            timer.Interval = 1000;
            timer2.Interval = 1000;
            timer3.Interval = 1000;
    
            timer.Start();
            timer2.Start();
            timer3.Start();
    
            Console.WriteLine("Press \'q\' to quit the sample.");
            while (Console.Read() != 'q') ;
        }
    
        static void timer3_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timer3.Stop();
            Console.WriteLine("Timer 3 Hit...");            
            timer3.Start();
        }
    
        static void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timer2.Stop();
            Console.WriteLine("Timer 2 Hit...");
            Thread.Sleep(2000);
            timer2.Start();
        }
    
        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timer.Stop();
            Console.WriteLine("Timer 1 Hit...");
            Thread.Sleep(10000);
            timer.Start();
        }
    }
    

    enter image description here

  • newbie
    newbie over 12 years
    All answers were correct, however I feel ThreadPool is the key component here.