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

new*_*bie 18 .net c# 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

Jam*_*are 22

根据MSDN的,在System.Timers.TimerElapsed事件触发它被称为在系统线程池中的线程:

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

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

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

参考:System.Timers.Timer上的MSDN


Bra*_*ner 5

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

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


Dav*_*nan 5

这是相当复杂的。该文件说,以下情况:

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

然后这个:

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

然后这个:

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

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