In our project, we have created a 'MaxFrequencyUpdater' for exactly that cause.
Only difference: if within 5 seconds a new call comes in, it is delayed and executed after the 5 seconds interval.
namespace Utils
{
public class MaxFrequencyUpdater
{
private readonly WinformsExceptionHandler _exceptionHandler;
private readonly string _name;
private readonly int _millis;
private MethodInvoker _currentMethod;
private DateTime _lastExecuted = DateTime.MinValue;
private readonly object _updaterLockObject = new object();
public MaxFrequencyUpdater(string name, int maxFrequencyInMillis, WinformsExceptionHandler exceptionHandler)
{
_name = name;
_exceptionHandler = exceptionHandler;
_millis = maxFrequencyInMillis;
}
public void Update(MethodInvoker method)
{
lock (_updaterLockObject)
{
_currentMethod = method;
}
Task.Run(HandleWork);
}
private void HandleWork()
{
lock (_updaterLockObject)
{
// No longer bother, someone else handled it already
if (_currentMethod == null) return;
var now = DateTime.Now;
var delay = (int)(_millis - now.Subtract(_lastExecuted).TotalMilliseconds);
// Post-pone if too soon
if (delay > 0)
{
Task.Delay(delay).ContinueWith(HandleWork);
}
else
{
try
{
_currentMethod.Invoke();
}
catch (Exception e)
{
_exceptionHandler.HandleException(e);
}
_lastExecuted = now;
_currentMethod = null;
}
}
}
}
}
usage:
_maxFrequencyUpdater.Update(() =>
{
doSomething();
});