26

我正在编写一个需要使用Timers 的应用程序,但可能很多。课程的可扩展性如何System.Threading.Timer?文档只是说它是“轻量级的”,但没有进一步解释。这些计时器是否被吸入代表 a 处理所有回调的单个线程(或非常小的线程池)中Timer,还是每个Timer都有自己的线程?

我想另一种表述问题的方式是:如何System.Threading.Timer实施?

4

4 回答 4

29

我这样说是为了回答很多问题:不要忘记框架的(托管)源代码是可用的。您可以使用此工具获取所有内容:http: //www.codeplex.com/NetMassDownloader

不幸的是,在这种特定情况下,很多实现都是在本机代码中,所以你看不到它......

不过,他们肯定使用池线程而不是每个计时器线程。

实现大量计时器的标准方法(这是内核在内部执行它的方式,我怀疑间接地是您的大型计时器集合如何结束)是维护按时间到到期排序的列表 - 所以系统只需要担心检查即将到期的下一个计时器,而不是整个列表。

粗略地说,这给了 O(log n) 用于启动计时器和 O(1) 用于处理正在运行的计时器。

编辑:刚刚在看 Jeff Richter 的书。他说(关于 Threading.Timer)它对所有 Timer 对象使用单个线程,该线程知道下一个计时器(即如上所述)何时到期,并酌情调用 ThreadPool.QueueUserWorkItem 进行回调。这样做的效果是,如果您没有在下一个回调到期之前完成对计时器的一个回调的服务,那么您的回调将重新进入另一个池线程。所以总而言之,我怀疑你会看到拥有大量计时器的大问题,但如果大量计时器在同一个计时器上触发和/或它们的回调运行缓慢,你可能会遭受线程池耗尽。

于 2008-08-28T08:12:24.270 回答
7

我认为您可能需要重新考虑您的设计(也就是说,如果您自己可以控制设计)。如果您使用的计时器太多以至于这实际上对您来说是一个问题,那么显然有一些整合的潜力。

这是几年前来自 MSDN 杂志的一篇好文章,它比较了三个可用的计时器类,并对它们的实现提供了一些见解:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

于 2008-08-28T07:23:25.433 回答
5

巩固他们。创建一个计时器服务并询问计时器。它只需要保持 1 个活动计时器(用于下一次到期呼叫)......

要使这比仅创建大量 Threading.Timer 对象有所改进,您必须假设这并不是 Threading.Timer 内部已经在做的事情。我很想知道你是如何得出这个结论的(我没有分解框架的原生部分,所以你很可能是对的)。

于 2008-08-28T09:34:14.137 回答
0

^^ 正如 DannySmurf 所说:合并它们。创建一个计时器服务并询问计时器。它只需要保留 1 个活动计时器(用于下一次到期调用)和所有计时器请求的历史记录,并在 AddTimer() / RemoveTimer() 上重新计算。

于 2008-08-28T08:46:29.463 回答