Skip to content

Instantly share code, notes, and snippets.

@wgross
Last active June 2, 2021 21:06
Show Gist options
  • Save wgross/5b12c48420be6b2a93f4436220d33f8b to your computer and use it in GitHub Desktop.
Save wgross/5b12c48420be6b2a93f4436220d33f8b to your computer and use it in GitHub Desktop.
Debounce and Throttle Event Handlers
// https://www.meziantou.net/debouncing-throttling-javascript-events-in-a-blazor-application.htm
Action<T> Debounce<T>(Action<T> action, TimeSpan interval)
{
if (action == null) throw new ArgumentNullException(nameof(action));
var last = 0;
return arg =>
{
// increment while calls of the event are coming
var current = System.Threading.Interlocked.Increment(ref last);
// first incoming event starts the delayed invocation of the action
Task.Delay(interval).ContinueWith(task =>
{
// excute action after a period of time where no changes happen
if (current == last)
{
action(arg);
}
});
};
}
Action<T> Throttle<T>(Action<T> action, TimeSpan interval)
{
if (action == null) throw new ArgumentNullException(nameof(action));
// captured in closure:
// .. the delivering delayed task
Task task = null;
// .. a lock handle
var l = new object();
// .. a storage for the calling args
T args = default;
return (T arg) =>
{
// the latest calling args are kept for later use
args = arg;
// if the delayed delivery is already initialized, return
if (task != null)
return;
// starts the delayed deleivery task, once!
lock (l)
{
// double locking...
if (task != null)
return;
// after exipry of the interval the latest args are delivered to the receiver
task = Task.Delay(interval).ContinueWith(t =>
{
action(args);
task = null;
});
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment