代码之家  ›  专栏  ›  技术社区  ›  Alan

system.timers.timer/threading.timer vs thread with whileloop+thread.sleep用于定期任务

  •  44
  • Alan  · 技术社区  · 16 年前

    在我的申请中,我必须定期向“兄弟”申请发送心跳信号。

    使用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)...
    
    4 回复  |  直到 16 年前
        1
  •  32
  •   Justin Niessner    16 年前

    System.Threading.Timer 我有投票权。

    system.timers.timer用于基于服务器的(您的代码在主机上作为服务器/服务运行,而不是由用户运行)计时器功能。

    一个带有while循环和thread.sleep命令的线程,考虑到.NET中存在更强大的计时器机制,这确实是一个坏主意。

        2
  •  23
  •   LBushkin    16 年前

    Server Timers 是一种不同于睡眠线程的生物。

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

    另一方面,计时器可以在任何线程上引发事件,从而实现更好的调度功能。但是,使用计时器的成本在代码中稍微复杂一点,而且您可能无法控制哪个线程运行计时器事件触发的逻辑。来自文档:

    基于服务器的计时器设计用于 与工作线程一起使用 多线程环境。服务器 计时器可以在线程之间移动到 处理引发的经过事件, 结果比 在上引发事件的Windows计时器 时间。

    另一个考虑因素是计时器在线程池线程上调用其经过的委托。根据逻辑的耗时和/或复杂程度,您可能不想在线程池中运行它—您可能需要一个专用的线程。计时器的另一个因素是,如果处理时间足够长,则可能会在另一个线程上再次(同时)引发计时器事件-如果正在运行的代码不是为了并发而设计或构造的,则这可能是一个问题。

    不要混淆 服务器计时器 用“ Windows Timers “。后者通常指的是可以传递到窗口的wm_计时器消息,允许应用程序在其主线程上调度和响应定时处理,而不需要休眠。但是,Windows计时器也可以引用 Win API for low-level timing (与wm_计时器不同)。

        3
  •  21
  •   johnny g    16 年前

    既不:

    睡觉通常是不受欢迎的(不幸的是,我记不起细节,但首先,它是一个不可中断的“障碍”),以及 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 )通过线程安全信号(如上面的优雅终止)保证真正的块。最坏的情况下,它是 Sleep

    希望这有帮助:)

        4
  •  1
  •   spender    16 年前

    我发现唯一真正可伸缩的计时器实现是 System.Threading.Timer . 如果您处理的是大量的计划项目,那么其他所有实现看起来都是伪造的。