I have the following problem. I want to write a class that handles events and passes it through but reduce its number if there recently was an event. Basically it is debounce. However there is a slight change that if we don't receive events for a while and the latest event was skipped we want to emit this event.
I wrote the following
public class Throttle
{
private string _latest;
private DateTime _date = DateTime.MinValue;
private static TimeSpan _timeout = TimeSpan.FromSeconds(2);
private readonly Timer _timer;
public Throttle()
{
_timer = new Timer(OnTimer);
}
public void Handle(string e)
{
lock (_timer)
{
var now = DateTime.Now;
if (now - _date < _timeout)
{
_latest = e;
_timer.Change(TimeSpan.FromSeconds(1), Timeout.InfiniteTimeSpan);
}
else
{
_date = now;
_latest = null;
_timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);
HandleNext(e);
}
}
}
private void OnTimer(object state)
{
lock (_timer)
{
if (_latest == null)
{
return;
}
var e = _latest;
_latest = null;
_date = DateTime.Now;
HandleNext(e);
}
}
private void HandleNext(string s)
{
Console.WriteLine(s);
}
}
It behaves as I want. However when the number of Throttle
classes gets high, it noticeably consumes CPU in comparison to version without the timer. However there is no way I can skip the the latest event or postpone it for a long time.
What can you suggest to make it more efficient? And what exactly is the problem?