Search code examples
c#multithreadingtimersystem.timers.timer

Why does System.Timers.Timer create multiple threads when it fires the Elapsed events?


When I create a System.Timers.Timer such as...

private System.Timers.Timer m_checker = new System.Timers.Timer();
public MyClass()
{
    Debug.WriteLine("[threadid:" + Thread.CurrentThread.ManagedThreadId + "] Main Thread");
    m_checker.Elapsed += m_checker_Elapsed;
    m_checker.Interval = 1000;
    m_checker.Start();
}

private void m_checker_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Debug.WriteLine("[threadid:" + Thread.CurrentThread.ManagedThreadId + "]");
}

Results with interval set to 1000:

/*
[threadid:10] Main Thread
[threadid:7]
[threadid:7]
[threadid:7]
[threadid:12]
[threadid:7]
[threadid:12]
etc...
*/

Results with interval set to 2000:

/*
[threadid:10] Main Thread
[threadid:7]
[threadid:7]
[threadid:7]
[threadid:7]
etc...
*/

I see that the Elapsed event is showing different threads when it is firing. Although when I change the Interval value to something higher such as 2000 (instead of the 1000) it seems to stay on the same thread.

Why is that?

I'm wanting a timer that fires on it's own thread but just fires on the one thread and not multiple threads.


Solution

  • It does it because that's the way it was written.

    https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx

    The server-based System.Timers.Timer class is designed for use with worker threads in a multithreaded environment. Server timers can move among threads to handle the raised Elapsed event . . .

    FWIW, Microsoft recommends that you not use it:

    The Timer class is available in the .NET Framework only. It is not included in the .NET Standard Library and is not available on other platforms, such as .NET Core or the Universal Windows Platform. On these platforms, as well as for portability across all .NET platforms, you should use the System.Threading.Timer class instead.

    The Timer class is now available in the .NET Standard Library as of .NET Standard 2.0. Obviously, the comment above was correct when it was written...3+ years ago. If you need to go back to .Net Standard Version 1.6 or sooner, then YES, the above comment is accurate.