11

我想知道该Timer组件以及由于它的使用或其使用的多个实例而产生的负面影响(如果有的话)。在实践中,一次应该在一个项目中使用多少个计时器是否应该有限制?

4

2 回答 2

15

好吧,一切都是相对的,但 System.Windows.Forms.Timer 是一个非常昂贵的对象。它通过创建一个隐藏窗口来工作,这是使底层 winapi SetTimer() 函数工作所需的。这个窗口不是共享的,每个定时器对象都有自己的窗口。窗口通常是更昂贵的操作系统对象之一。

所以一个非常硬的上限是你不能拥有超过 10,000 个启用的计时器。Windows 拒绝允许应用程序创建那么多窗口。考虑到在一个桌面会话中运行的所有进程的所有窗口都需要共享一个公共堆,您应该远离该限制。或者换句话说,创建很多窗口但保持在 10,000 个配额以下会对其他进程产生负面影响,当堆用完时可能会使它们失败。

我想说一个合理的上限徘徊在 100 左右。假设所有这些计时器都有不同的 Tick 事件处理程序,那么通常需要跟踪大量移动部件。如果他们不这样做,那么您应该以不同的方式解决这个问题,您只需要一个计时器来测量任意数量的间隔。与您在手腕上佩戴一块手表进行约会的方式大致相同。为此,您可以将到期时间存储在 SortedList 中,并仅为第一个到期时间启动计时器。当它滴答作响时,处理列表中到期时间已过的条目并重复。添加或删除到期时间时,请停止计时器并在有新的第一个到期时间时重新启动它。

于 2013-01-14T15:41:50.573 回答
1

我假设你的意思是winforms计时器对象所以,

从文档:

Timer 用于以用户定义的时间间隔引发事件。此 Windows 计时器专为使用 UI 线程执行处理的单线程环境而设计。它要求用户代码具有可用的 UI 消息泵,并且始终从同一个线程操作,或者将调用编组到另一个线程。

使用此计时器时,使用 Tick 事件执行轮询操作或在指定时间段内显示启动画面。只要 Enabled 属性设置为 true 并且 Interval 属性大于零,就会根据 Interval 属性设置每隔一段时间引发 Tick 事件。

因此,如果您开始使用计时器打包您的应用程序,那么逐行阅读该代码,您很快就会为 UI 渲染时间竞速间隔事件。

例如:您有一个时钟应用程序,它使用计时器来运行时钟。每隔 1 秒,您就会让应用程序渲染双手。

在这个应用程序中,您还可以让用户根据需要定义任意数量的“警报”。每个人都会创建一个新的计时器,该计时器将在设定的时间触发。这些警报也可以是循环的。也就是说,您允许用户设置每 x 秒响一次的“警报”。

现在假设用户有一个长时间运行的任务(访问数据库、网络资源、将 PI 计算到 1500 个字符等),该任务发生在周期性警报上。现在假设用户有 10 个长时间运行的任务需要按顺序执行,并且需要以 3 4 和 5 秒的间隔发生。

这些计时器的行为不适用于此应用程序,因为会发生以下情况:

  • 时钟将在“警报”执行期间停止渲染
  • 警报可能会相互重叠,因此它们会排队但不会在它们应该发生的时候发生,因为 UI 线程正在同步处理所有消息。
  • 您最终会得到一个无响应的 UI,它不能满足您的需求。

因此,尽我所能回答您的实际问题;不一定需要限制计时器的数量,只需考虑它们触发的时间间隔以及处理事件处理程序所需的时间。

如果您使用计时器来触发单独的处理线程,这些线程最终将返回到 UI 线程并进行更改,那么在您遇到目标性能的上限之前,没有可行的限制机器。也就是说,在某些时候,定时器的数量可能会很大,以至于您正在调用更多的定时器事件并将消息队列阻塞到表单呈现受到影响的程度。

简而言之:

负面影响:

  • 计时器在 UI 线程中运行,因此它们处于阻塞状态
  • 如果您的时间间隔短于处理事件处理程序所需的时间,它们可能会出现意外行为。

在实践中,您唯一需要限制计时器的使用,就像用户无法控制的任何组件一样,是它们是否开始影响用户体验。

我希望这比我写它时的感觉要少得多。

于 2013-01-14T15:41:14.967 回答