如何在不使用Rx Framework的情况下限制事件的速度

我想限制一个事件的速度,如何在不使用Microsoft Rx框架的情况下实现这一目标。 我在Rx的帮助下做到了这一点。 但我正在尝试的是,我需要根据时间段限制Map的View更改事件。 是否可以在不使用Rx的情况下实现相同的function。

我不允许使用Rx,我必须保持二进制大小尽可能小。

如果您的事件类型为EventHandler ,则此方法有效。 它为受限制的事件处理程序创建一个包装器:

 private EventHandler CreateThrottledEventHandler( EventHandler handler, TimeSpan throttle) { bool throttling = false; return (s,e) => { if(throttling) return; handler(s,e); throttling = true; Task.Delay(throttle).ContinueWith(_ => throttling = false); }; } 

像这样附上:

 this.SomeEvent += CreateThrottledEventHandler( (s,e) => Console.WriteLine("I am throttled!"), TimeSpan.FromSeconds(5)); 

虽然,您应该存储从CreateThrottledEventHandler返回的处理程序,如果您需要使用-=稍后取消它。

我相信以下要求在’限制’事件处理程序中是必不可少的:

  • 一个事件立即引发。
  • 后续事件 – 在限制期内发生 – 将被忽略
  • 一旦限制期结束, 保证在限制期间发生的最后一个事件将被提升。

考虑到这些要求,以前接受的答案并不令人满意; 它正确地满足了前两个要求,但它并不能保证最终会引发最后一个事件。 我认为这一点特别重要,因为以高频率提出的事件通常代表“状态变化”和/或“用户请求”; 我们总是希望收到状态或用户交互更改的最新更新。

为了满足所有这些要求,我创建了自己的通用“ThrottledEventHandler”类。

 public class ThrottledEventHandler where TArgs : EventArgs { private readonly EventHandler _innerHandler; private readonly EventHandler _outerHandler; private readonly Timer _throttleTimer; private readonly object _throttleLock = new object(); private Action _delayedHandler = null; public ThrottledEventHandler(EventHandler handler, TimeSpan delay) { _innerHandler = handler; _outerHandler = HandleIncomingEvent; _throttleTimer = new Timer(delay.TotalMilliseconds); _throttleTimer.Elapsed += Timer_Tick; } private void HandleIncomingEvent(object sender, TArgs args) { lock (_throttleLock) { if (_throttleTimer.Enabled) { _delayedHandler = () => SendEventToHandler(sender, args); } else { SendEventToHandler(sender, args); } } } private void SendEventToHandler(object sender, TArgs args) { if (_innerHandler != null) { _innerHandler(sender, args); _throttleTimer.Start(); } } private void Timer_Tick(object sender, EventArgs args) { lock (_throttleLock) { _throttleTimer.Stop(); if (_delayedHandler != null) { _delayedHandler(); _delayedHandler = null; } } } public static implicit operator EventHandler(ThrottledEventHandler throttledHandler) { return throttledHandler._outerHandler; } } 

用法看起来像这样:

 myObject.MyFrequentlyRaisedEvent += new ThrottledEventHandler(MyActualEventHandler, TimeSpan.FromMilliseconds(50));