4

我正在处理设置为在经过一段时间后发生的超时,之后我想得到一个回调。现在我正在使用一个Timer在被触发时自行处理的方法来执行此操作。

public class Timeouter
{
    public void CreateTimeout(int timeout, Action onTimeout)
    {
        Timer t = null;
        t = new Timer(_ =>
            {
                onTimeout();
                t.Dispose();
            }, new object(), timeout, Timeout.Infinite);    
    }
}

我有点担心这个计时器的资源使用,因为它可能会被非常频繁地调用,因此会设置很多计时器来触发一次并自行处理。考虑到计时器是一个IDisposable,它会向我表明它确实使用某种昂贵的资源来完成它的任务。

  • 我是否过于担心 的资源使用情况Timer,或者解决方案是否可以?
  • 我还有其他选择吗?最好有一个计时器并根据需要调整它的频率来启动和停止它以适应其中的几个超时?任何其他可能更轻量级的选项可以在给定的时间段后执行一次任务?
4

4 回答 4

1

创建一个可以计时多个间隔的廉价计时器在直观上很简单。你只需要一个计时器。将其设置为最接近的到期时间。当它滴答作响时,为每个到期的计时器触发回调或事件。然后重复一遍,再次查看下一个到期时间的活动计时器列表。如果计时器更改其间隔,则只需再次重复搜索。

回调中可能会发生一些潜在的昂贵的事情。处理这个问题的最佳方法是在线程池线程上运行该代码。

这是对系统资源的非常节俭的使用,只有一个计时器和最便宜的线程。每当计时器的状态发生变化时,您都会为此付出一点开销,查看活动计时器列表的复杂度为 O(n),您可以使用 SortedList 使其大部分时间为 O(log(n))。但是哦是很小的。

您可以轻松地自己编写该代码。

但是您不必这样做, System.Timers.Timer已经以这种方式工作。不要帮忙。

于 2012-08-24T12:08:46.127 回答
1

.Net 有 2 或 3 个昂贵的计时器类。但是System.Threading.Timer,您使用的课​​程非常便宜。此类不使用内核资源或让线程休眠等待超时。相反,它对所有 Timer 实例仅使用一个线程,因此您可以轻松拥有数千个计时器,并且仍然获得很小的处理器和内存占用。您必须调用Dispose只是因为您必须通知系统停止跟踪某些计时器实例,但这并不意味着这是一个昂贵的类/任务。一旦达到超时,此类将安排回调由ThreadPool线程执行,因此它不会启动新线程或类似的东西。

于 2012-08-24T11:44:14.120 回答
1

虽然它不是答案,但由于篇幅原因,我将其添加为答案。

在服务器/客户端环境中,AFAIK 在服务器上使用 Timers 并不是最好的方法,如果你有胖客户端甚至瘦客户端,你应该在客户端设计一些轮询机制,如果它希望在服务器上执行某个操作本身(由于客户端在设置计时器后可能会断开连接,然后重新实例化并再次设置计时器,以此类推,导致您的服务器在将来的某个时间不可用(潜在的 DOS 攻击)),

或者考虑使用单个计时器策略来处理所有客户端,该策略实现滑动到期或客户端特定策略来处理它。

于 2012-08-24T11:26:15.753 回答
1

另一种选择是维护将超时的事物的排序列表,将它们添加到列表中,使用它们的到期时间而不是它们的持续时间,保持列表按到期时间排序,然后在它到期时从列表中弹出第一个项目.

您当然需要在辅助线程上执行大部分操作并调用您的回调。您实际上也不需要保持线程旋转,您可以在 add 方法上设置一个等待句柄,并将超时设置为(略小于)直到下一次超时到期的持续时间。有关超时等待的更多信息,请参见此处。

我不知道这是否比创建大量计时器更好。

于 2012-08-24T11:26:48.753 回答