System.Timers.Timer/Threading.Timer vs Thread with WhileLoop + Thread.Sleep for Periodic Tasks

Ala*_*lan 44 c# multithreading timer

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

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

心跳间隔为1秒.

while(!exit)
{
   //do work
   Thread.Sleep(1000);
}
Run Code Online (Sandbox Code Playgroud)

要么

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

Jus*_*ner 32

System.Threading.Timer有我的投票.

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

具有While循环和Thread.Sleep命令的线程确实是一个坏主意,因为在.NET中存在更强大的Timer mecahnisms.

  • System.Timers.Timer类实际上可以在用户模式应用程序中使用,就像System.Threading.Timer一样容易.在内部,System.Timers.Timer使用System.Threading.Timer作为它的内部计时机制,并且只包装它来处理设计时间问题...... (3认同)
  • 你有我的 (2认同)
  • @Alan:你有我的 (2认同)
  • 请注意,计时器会在任何线程池线程上引发它的tick事件,因此您必须处理重新进入和线程安全!我的投票是等待使用OS信号的handel,以便获得更高的计时准确性,并且所有内容都在你的线程内执行. (2认同)

LBu*_*kin 23

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

首先,根据您的线程的优先级以及正在运行的其他内容,您的睡眠线程可能会或可能不会被唤醒并计划在您询问的时间间隔运行.如果间隔足够长,并且调度精度并不重要,那么这Thread.Sleep()是一个合理的选择.

另一方面,定时器可以在任何线程上提升它们的事件,从而允许更好的调度功能.但是,使用定时器的成本在代码中会稍微复杂一些 - 而且您可能无法控制哪个线程运行定时器事件触发的逻辑.来自文档:

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

另一个考虑因素是计时器在ThreadPool线程上调用他们的Elapsed委托.根据逻辑的耗时和/或复杂程度,您可能不希望在线程池上运行它 - 您可能需要专用线程.另一个带有定时器的因素是,如果处理时间足够长,则可能会在另一个线程上再次(并发)引发timer事件 - 如果正在运行的代码不是为了并发而构建的,那么这可能是一个问题.

不要将服务器计时器与" Windows计时器 " 混淆.后者通常是指可以传递到窗口的WM_TIMER消息,允许应用程序在其主线程上安排和响应定时处理而不会休眠.但是,Windows计时器也可以参考Win API进行低级计时(与WM_TIMER不同).


joh*_*y g 21

都不是:)

睡觉通常是不受欢迎的(不幸的是我不记得细节,但对于一个,它是一个不间断的"块"),并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!
    }
}
Run Code Online (Sandbox Code Playgroud)

使用AutoResetEvent(或其表兄ManualResetEvent)保证带有线程安全信令的真正块(对于诸如上面的优雅终止之类的事情).在最坏的情况下,它是一个更好的替代品Sleep

希望这可以帮助 :)

  • 为什么是for循环而不是while? (6认同)
  • @gav,`while`同样适用,`for`是一种风格偏好. (3认同)