我正在编写一个需要使用Timer
s的应用,但可能还有很多。 System.Threading.Timer
类的可扩展性如何?文档只是说它“轻量级”,但没有进一步解释。这些计时器是否被吸引到代表Timer
处理所有回调的单个线程(或非常小的线程池)中,或者每个Timer
都有自己的线程?
我想另一种重新定义问题的方法是:System.Threading.Timer
如何实施?
答案 0 :(得分:29)
我在回答很多问题时这样说:不要忘记框架的(托管)源代码是可用的。您可以使用此工具获取所有内容:http://www.codeplex.com/NetMassDownloader
不幸的是,在这个特定的情况下,很多实现都是在本机代码中,所以你不用看它......
他们肯定使用池线程而不是每个计时器的线程。
实现大量计时器的标准方法(这是内核在内部执行的方式,我怀疑是间接的,你的大型计时器最终会如何结束)是按时间排序,直到到期为止 - 所以系统只需要担心检查即将到期的下一个计时器,而不是整个列表。
粗略地说,这给出了启动计时器的O(log n)和处理运行计时器的O(1)。
编辑:刚刚看过杰夫里希特的书。他说(Threading.Timer)它为所有Timer对象使用单个线程,该线程知道下一个计时器(即如上所述)何时到期,并根据需要调用ThreadPool.QueueUserWorkItem进行回调。这样做的结果是,如果在下一个到期之前没有在计时器上完成一个回调服务,那么你的回调将重新进入另一个池线程。总而言之,我怀疑你会看到有很多计时器的大问题,但是如果大量的计时器在同一个计时器上触发和/或它们的回调运行缓慢,你可能会遇到线程池耗尽。
答案 1 :(得分:7)
我想您可能想重新考虑您的设计(也就是说,如果您自己可以控制设计)。如果你使用这么多计时器,这实际上是你的一个问题,那么显然有一些潜在的合并。
这是几年前来自MSDN杂志的一篇好文章,它比较了三个可用的计时器类,并对它们的实现提供了一些见解:
答案 2 :(得分:5)
巩固他们。创建一个计时器 服务并要求为计时器。 它只需要保持1活跃 计时器(用于下次到期通话)......
为了比仅仅创建大量Threading.Timer对象更好,你必须假设它不是Threading.Timer在内部已经完成的。我有兴趣知道你是如何得出这个结论的(我没有反汇编框架的本地部分,所以你很可能是正确的。)
答案 3 :(得分:0)
^^正如DannySmurf所说:巩固他们。创建计时器服务并询问计时器。它只需要保留1个活动计时器(用于下一个到期呼叫)和所有计时器请求的历史记录,并在AddTimer()/ RemoveTimer()上重新计算。