System.Timers.Timer / Threading.Timer与线程与WhileLoop + Thread.Sleep的周期性任务

在我的应用程序中,我必须定期发送心跳到“兄弟”应用程序。

使用System.Timers.Timer / Threading.Timer或使用带有while循环和Thread.Sleep的线程可以更好地完成这项工作吗?

心跳间隔是1秒。

while(!exit) { //do work Thread.Sleep(1000); } 

要么

 myTimer.Start( () => { //do work }, 1000); //pseudo code (not actual syntax)... 

System.Threading.Timer有我的投票。

System.Timers.Timer用于基于服务器(您的代码作为主机上的服务器/服务运行,而不是由用户运行)计时器function。

带有While循环和Thread.Sleep命令的线程在.NET中存在更健壮的Timer定时器是一个糟糕的主意。

服务器计时器是与睡眠线程不同的生物。

首先,根据线程的优先级以及运行的内容,您的睡眠线程可能会或不会被唤醒,并按您要求的时间间隔运行。 如果时间间隔足够长,并且调度的精度并不重要,那么Thread.Sleep()是一个合理的select。

另一方面,定时器可以在任何线程上提升事件,从而提供更好的调度function。 然而,使用定时器的代价在你的代码中稍微复杂一些 – 而且你可能无法控制哪个线程运行定时器事件触发的逻辑。 从文档:

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

另一个考虑是计时器在ThreadPool线程上调用它们的Elapsed委托。 根据你的逻辑如何耗时和/或复杂,你可能不想在线程池上运行它 – 你可能需要一个专用的线程。 定时器的另一个因素是,如果处理时间足够长,定时器事件可能会在另一个线程上再次同时发生 – 如果正在运行的代码不是为了并发而构build的,那么这可能是一个问题。

不要将服务器计时器与“ Windows计时器 ”混淆。 后者通常是指WM_TIMER消息可以传递给一个窗口,允许应用程序调度和响应其主线程上的定时处理,而不睡觉。 但是,Windows定时器也可以参考Win API的低级定时 (与WM_TIMER不一样)。

都不:)

睡觉通常是皱眉(不幸的是我不记得的细节,但一个,这是一个不可分割的“块”),和Timer有很多的行李。 如果可能的话,我会推荐System.Threading.AutoResetEvent

 // initially set to a "non-signaled" state, ie will block // if inspected private readonly AutoResetEvent _isStopping = new AutoResetEvent (false); public void Process() { TimeSpan waitInterval = TimeSpan.FromMilliseconds (1000); // will block for 'waitInterval', unless another thread, // say a thread requesting termination, wakes you up. if // no one signals you, WaitOne returns false, otherwise // if someone signals WaitOne returns true for (; !_isStopping.WaitOne (waitInterval); ) { // do your thang! } } 

使用AutoResetEvent (或其表亲ManualResetEvent )可以保证带有线程安全信号的真正的块(例如上面的正常终止)。 在最坏的情况下,这是一个更好的selectSleep

希望这可以帮助 :)

我发现,唯一的计时器实现,实际缩放是System.Threading.Timer 。 所有其他的实现看起来都非常虚假,如果你正在处理一个不重要的计划项目数量。