Throttle an Event Handler

Using Rx, you want to use the Sample method or Throttle.

Something like this should work (untested):

Observable
  .FromEventPattern<TextChangedEventArgs>(myUiElement, "MouseEnter")
  .Sample(TimeSpan.FromSeconds(1))
  .Subscribe(x => ... Do Stuff Here ...);

The difference between Sample and Throttle is that Sample will take a value every 1 second no matter when the last value was taken, whereas Throttle will take a value and then wait another 1 second before taking another.

It probably depends on what you are shooting for...


You could use reactive extensions, but you could accomplish this just as easily with a timer.

Set a flag along with a Timer. When the timer tick event fires, set the flag to false, disable the timer, and run the code for your event. Then, in your control event handlers, have the handler code skipped if the flag is set.

bool flag;
DispatcherTimer timer;

public constructor()
{
    timer = new DispatcherTimer();
    timer.Interval = TimeSpan.FromSeconds(1);
    timer.Tick += (s,e) => {
        flag = false;
        timer.Stop()
        DoThrottledEvent();
    }
}

void mouse_enter(object sender, MouseEventArgs args)
{
    if(!flag)
    {
        flag = true;
        timer.Start();
    }
}

void DoThrottledEvent()
{
    //code for event here
}

Reactive extensions introduces an extra dependency, but they are a bit of fun. If you are interested, go for it!


Another approach would be to use a private field to keep track of the "time" when the last mouse event occurred, and only continue processing if that time was more than one second ago.

DateTime _lastMouseEventTime = DateTime.UtcNow;

void OnMouseEnter(object sender, MouseEventArgs e)
{
    DateTime now = DateTime.UtcNow;
    if (now.Subtract(_lastMouseEventTime).TotalSeconds >= 1)
    {
        // do stuff...
    }
    _lastMouseEventTime = now;
}

This ensures that "stuff" gets done at least one second apart, which is what I think you were asking for.

Tags:

C#

Wpf

Throttling