2011-10-25 40 views
16

我试图了解什么时候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(); 
    } 
} 

enter image description here

+1

是的,定时器是线程化的。 – qJake

+0

是的,他们运行在不同的线程。 –

回答

20

按照MSDN上System.Timers.TimerElapsed事件触发它被称为在系统线程池中的线程:

如果SynchronizingObject的属性是没什么,经过的事件是在一个线程池升起线。如果处理Elapsed事件的持续时间比Interval长,则可能会在另一个ThreadPool线程上再次引发该事件。在这种情况下,事件处理程序应该是可重入的。

由于SynchronizingObject默认值为空,那么所有你过去的事件将是对线程池处理。所以,它取决于线程池的完整性,如果有空闲线程,那么每个经过的事件很可能在单独的线程上并发运行。但是,如果由于某种原因,系统线程池已经被完全使用,那么可能已过期的事件将按照它们的计划进行序列化。

重点是:“它要看”。也就是说,只要池中有空闲线程,它们将被允许并行运行。

参考:MSDN on System.Timers.Timer

+0

所有的答案都是正确的,但我觉得ThreadPool是这里的关键组件。 – newbie

4

他们必须的,因为Thread.Sleep是一个阻塞调用。如果他们在同一个线程上运行,其他定时器都不会触发。你可以输出System.Threading.Thread.CurrentThread.ManagedThreadId以确认。

2

是的,每一个经过的被调用时,回调是在自己的线程解雇。

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

4

这很复杂。 documentation指出以下内容:

基于服务器的Timer专为在多线程环境中与工作线程一起使用而设计。服务器定时器可以在线程之间移动以处理引发的Elapsed事件,从而比按时提升事件的Windows定时器更准确。

,然后这样的:

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

,然后将此:

如果使用计时器与用户界面元件,诸如形式或控制,无需将所述计时器的用户界面元素上,分配的形式或控制包含定时器到SynchronizingObject属性,以便将事件封送到用户界面线程。

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

相关问题