为什么 System.Timers.Timer 在触发 Elapsed 事件时创建多个线程?

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

当我创建 System.Timers.Timer 例如...

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 + "]");
}

间隔设置为 1000 的结果:

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

间隔设置为 2000 的结果:

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

我看到 Elapsed 事件在触发时显示不同的线程。虽然当我将 Interval 值更改为更高的值,例如 2000(而不是 1000)时,它似乎停留在同一个线程上。

这是为什么?

我想要一个在它自己的线程上触发但只在一个线程上触发而不是在多个线程上触发的计时器。

它使用线程池来执行处理程序。根据您的程序正在执行的操作,您的线程池中可能有一个或多个线程,并且您可能有也可能没有不同的线程来处理任何给定的请求。

之所以这样做,是因为它是这样写的。

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 建议您不要使用它:

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.

从 .NET Standard 2.0 开始,Timer class 现在可以在 .NET Standard 库中使用。显然,上面的评论是正确的……3 多年前写的。如果您需要回到 .Net Standard Version 1.6 或更早的版本,那么是的,以上评论是准确的。