对于Windows服务,哪个更好,等待旋转还是计时器?

时间:2009-07-08 17:39:51

标签: c# .net sleep waithandle

This question about Timers for windows services让我思考:

说我有(并且我做)一个等待WaitHandle的Windows服务,当它被唤醒时,它潜入等待旋转,如下面的流程图所示

wait spin diagram http://www.86th.org/waitspin.jpg

我很好奇,如果使用计时器会优于wait-spin loop(有时称为旋转等待)。老实说,除了我自己的修补之外,我从来没有使用计时器。

我没有任何切换的计划,除非差异很大并且使用Timer的好处是惊人的。但是,我非常感兴趣的是人们对这个项目未来发展的看法。

让我知道这应该是一个维基

6 个答案:

答案 0 :(得分:5)

我没有看到你从计时器中获得任何好处。无论如何,在睡眠呼叫时,你基本上都是一个计时器,而且你不是一个带宽占用,因为睡眠会产生时间片。有一个明确的计时器唤醒并调用你只会使代码复杂化。

我不会说你正在进行旋转等待,因为我通常认为旋转等待是一种无法入睡的东西。它只会消耗等待转发信号的所有处理器时间。

答案 1 :(得分:2)

暂停一个线程并等待一个超时的句柄基本上是同样的事情。我猜测定时器本质上是使用睡眠实现的,所以也没有太大区别。换句话说,您可以通过在单个循环中等待句柄超时并检查等待被释放的原因(数据可用或超时)来简化代码,而不是实现单独的等待和睡眠循环。比独立循环略高效。

理想情况下,您根本不会使用sleep,只需依靠数据生成代码来正确引发消耗代码等待的事件,并在事件源消失时处理一个很长的超时。

如果数据是外部的,例如在套接字或其他输入设备上,那么通常可以设置句柄以允许等待数据变得可用 - 在这种情况下不需要轮询,因为事件将始终发出信号。数据已准备好供消费。

答案 2 :(得分:1)

我们使用线程。它们不仅像计时器那样执行,而且还为我们提供了在线程处于休眠状态时执行其他操作的句柄。

答案 3 :(得分:1)

我认为这实际上取决于您的要求:

  1. 运行任务 每次 5分钟(例如,12:00,12:05,12:10,......)
  2. 完成当前任务后,在 5分钟后运行下一个任务
  3. 对于案例1而言,计时器似乎很容易,而案例2中的Thread.Sleep似乎很容易,即使Timer和Thread.Sleep可以同时执行这两个操作。

    事实上,我对类似的问题(Windows service scheduled execution)提出了更长的评论(包括对案例1的一些考虑)。

答案 4 :(得分:1)

轮询很糟糕,几乎总是可以避免。偶尔对于琐碎的事情,它比避免它所需的复杂性要差。

您查询“有数据吗?”的来源是什么?你不能变成某种句柄等待吗?

此外,在严重的代码(如服务)中不要Sleep()任何大量的时间。您可以执行的唯一阻止是WaitFor[Single|Multiple]Objects(...),其中句柄列表包括在关闭进程时触发的事件。找到您呼叫Sleep(millisec)的所有位置,并将其替换为WaitForSingleObjects(g_shutdownEvent, millisec)

答案 5 :(得分:0)

正如Raymond Chen所解释的那样,"Yeah, whatever."如果你的数据准备就绪时无法找到通知的方法那么你的SOL。