我正在处理请求超时机制。我最初的方法是为每个请求创建一个System.Threading.Timer。并发请求的数量可以扩展到数千个。
我想知道是否应该创建一个TimeoutScheduler,它在内部只使用一个计时器而不是每个请求一个。
任何知道System.Threading.Timer内部的人都能给我一些见解,看看TimeoutScheduler是不是一个好主意,或者它是否只会尝试优化已经足够高效的东西。
注意:对于我的场景,计时器精度并不重要。
(我使用System.Threading.Timer对很多并发计时器进行了一些性能测试。它似乎可以很好地扩展,但我不确定它是否会给实际系统带来不必要的压力)
答案 0 :(得分:11)
我将指导您阅读Raymond Chen的这篇文章:
What is the maximum number of timers a program can create?
从技术上讲,创建数千个没有问题。请注意,这些使用全局系统资源,因此如果你发疯了,最终会达到上限和/或开始使其他程序(包括Windows本身)挨饿。
同样确保在完成计时器后处理计时器,否则最终会导致巨大的资源泄漏。
我不得不说,这听起来像你可以用一个计时器实现的东西;只需维护一个活动请求和超时的字典,并在每个标记上,浏览整个字典并检查每个条目。您可以通过将其作为排序列表来提高性能;这样,如果再过5分钟没有超时,则在查看第一个条目后,tick方法将退出。
除了上述内容之外,您还可以动态调整勾选间隔,以便在下一个请求被安排超时时触发;然后在每个刻度线上,重新安排下一个刻度到下一个超时。这几乎不占用任何系统资源(只需一个计时器),并且速度非常快(就像你的每个请求的一个计时器一样,你只会在请求实际到期时运行昂贵的代码)。
即使您可以创建数千个计时器,上述方法也会更好地扩展,并且更容易进行测试和维护。
答案 1 :(得分:1)
超时调度程序是个好主意,但Timers是执行率最低的。如果这是用于调度超时,则最可靠的选项将是跟踪其他线程的超时以及使用QueryPerormanceCounter和QueryPerformanceFrequency更新的线程。这些将是阻塞类,但在他们自己的线程内部并不重要。您还可以考虑使超时调度程序以更高的优先级运行。
答案 2 :(得分:1)
System.Threading.Timer在ThreadPool上执行它的TimerCallback,创建1000可能会导致线程池饥饿。
使用TimerCallback委托指定希望Timer执行的方法。定时器委托是在构造定时器时指定的,不能更改。该方法不会在创建计时器的线程上执行;它在系统提供的ThreadPool线程上执行。
System.Timers.Timer的行为方式相同。 TimeoutScheduler是最佳选择。
答案 3 :(得分:0)
听起来像是quartz.net的工作。
答案 4 :(得分:0)
我知道这很老了,但是这些响应与我一贯的做法背道而驰,因此我检查了“参考源”,但都错了。
创建数千个计时器完全没有问题,内部所有计时器都在系统timer queue中运行,它们不创建系统计时器,该队列由单个线程处理,因此分配的唯一资源是是每个计时器的等待句柄,而这些计时器确实很轻巧。