System.Timers.Timer是否在独立的线程中运行?

我试图了解System.Timers.Timer何时引发已发生的事件,是否在独立线程中引发?

我的下面的例子似乎暗示三个计时器在他们自己的线程中独立运行:

 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(); } } 

在此处输入图像描述

根据MSDN,在System.Timers.TimerElapsed事件触发时,它会在系统线程池中的一个线程上调用:

如果SynchronizingObject属性为Nothing,则在ThreadPool线程上引发Elapsed事件。 如果Elapsed事件的处理持续时间超过Interval,则可能会在另一个ThreadPool线程上再次引发该事件。 在这种情况下,事件处理程序应该是可重入的。

由于SynchronizingObject的默认值为null,因此将在线程池上处理所有已用事件。 因此,它取决于线程池的完整程度,如果有空闲线程,那么每个已发生的事件很可能在不同的线程上并发运行。 但是,如果出于某种原因,系统线程池已经完全使用,则可能会在计划时序列化已过去的事件。

重点是:“这取决于。” 也就是说,只要池中有空闲线程,就可以允许它们并行运行。

参考: System.Timers.Timer上的MSDN

根据你的代码,它们必须是,因为Thread.Sleep是一个阻塞调用。 如果它们在同一个线程上运行,其他任何计时器都不会触发。

你可以在每一个中输出System.Threading.Thread.CurrentThread.ManagedThreadId来确定。

这很复杂。 文档说明如下:

基于服务器的Timer设计用于multithreading环境中的工作线程。 服务器计时器可以在线程之间移动以处理引发的Elapsed事件,从而在准时引发事件时比Windows计时器更准确。

然后这个:

如果SynchronizingObject属性为null,则在ThreadPool线程上引发Elapsed事件。 如果Elapsed事件的处理持续时间超过Interval,则可能会在另一个ThreadPool线程上再次引发该事件。 在这种情况下,事件处理程序应该是可重入的。

然后这个:

如果将Timer与用户界面元素(如窗体或控件)一起使用,而不将计时器放在该用户界面元素上,请将包含Timer的窗体或控件分配给SynchronizingObject属性,以便将事件封送到用户界面线程。

所以,你的问题没有简单的答案“它是在一个独立的线程中提出的吗?” 这取决于很多事情。

是的,每次调用Elapsed时,都会在自己的线程上触发回调。

此外,没有什么能阻止一个Elapsed事件处理程序在前一个事件处理程序完成之前触发。 例如,如果您的计时器每500毫秒触发一次,但Elapsed事件处理程序代码需要2秒才能完成,则Elapsed代码可以访问相同的资源(非线程安全的对象,文件等)。