I\'m listening to a hardware event message, but I need to debounce it to avoid too many queries.
This is an hardware event that sends the machine status and I have t
I needed something like this but in a web-application, so I can't store the Action in a variable, it will be lost between http requests.
Based on other answers and @Collie idea I created a class that looks at a unique string key for throttling.
public static class Debouncer
{
static ConcurrentDictionary _tokens = new ConcurrentDictionary();
public static void Debounce(string uniqueKey, Action action, int seconds)
{
var token = _tokens.AddOrUpdate(uniqueKey,
(key) => //key not found - create new
{
return new CancellationTokenSource();
},
(key, existingToken) => //key found - cancel task and recreate
{
existingToken.Cancel(); //cancel previous
return new CancellationTokenSource();
}
);
Task.Delay(seconds * 1000, token.Token).ContinueWith(task =>
{
if (!task.IsCanceled)
{
action();
_tokens.TryRemove(uniqueKey, out _);
}
}, token.Token);
}
}
Usage:
//throttle for 5 secs if it's already been called with this KEY
Debouncer.Debounce("Some-Unique-ID", () => SendEmails(), 5);
As a side bonus, because it's based on a string key, you can use inline lambda's
Debouncer.Debounce("Some-Unique-ID", () =>
{
//do some work here
}, 5);