3

如果我有两个系统计时器分别在 10 秒和 20 秒触发事件,那么对事件函数的调用是多线程的吗?在下面的场景中,我有分别以 10 秒和 12 秒间隔触发事件的计时器。函数 'My10sEvent' 应该首先被调用。如果它是一个需要 8 秒运行的慢函数,它会阻塞另一个事件(tmr12s),还是第二个事件会在 12 秒时按时触发?

System.Timers.Timer tmr10s = new System.Timers.Timer(10000.0);
tmr10s.Enabled = true;
tmr10s.Elapsed += new ElapsedEventHandler(My10sEvent);

System.Timers.Timer tmr12s = new System.Timers.Timer(12000.0);
tmr12s.Enabled = true;
tmr12s.Elapsed += new ElapsedEventHandler(My12sEvent);

Thread.Sleep(System.Threading.Timeout.Infinite); //sleep indefinitely to let the above events fire
4

3 回答 3

5

CLR 使用专用线程来跟踪活动的 System.Timers.Timer 和 System.Threading.Timer 计时器。Elapsed 事件在从线程池中拉出的另一个线程上引发。

所以,是的,它们一直在滴答作响,而不会相互影响。您必须非常小心,您的 Elapsed 事件处理程序很有可能在它仍在执行时再次被调用。当花费的时间超过间隔时会发生这种情况。或者更糟的是,当机器负载很重或者你有很多活动的线程池线程时。如果您的事件处理程序不是线程安全的,这可能会导致很难诊断故障。几乎从来没有。将计时器的 AutoReset 属性设置为 false 是避免此问题的一种简单方法。

于 2011-06-14T06:04:31.453 回答
3

如果您使用 System.Threading.Timer 或在没有 SynchronizingObject 的情况下调用 System.Timers.Timer,它看起来不会阻塞。

类似的问题:C# Timers 在单独的线程上运行吗?

于 2011-06-14T05:46:44.437 回答
1

System.Timers.Timer文档中:

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

所以是的,是的。

此外,来自System.Timers.Timer.SynchronizingObject财产文件:

当 SynchronizingObject 为 null 时,将在系统线程池中的线程上调用处理 Elapsed 事件的方法。有关系统线程池的更多信息,请参阅 ThreadPool。

因此,除非设置了 SynchronizingObject,否则在线程池线程上引发事件。

于 2011-06-14T05:49:18.570 回答