Skip to content

Instantly share code, notes, and snippets.

@MysteryDash
Last active February 26, 2019 00:00
Show Gist options
  • Save MysteryDash/cfef31a433e08c4638427e8d717ead19 to your computer and use it in GitHub Desktop.
Save MysteryDash/cfef31a433e08c4638427e8d717ead19 to your computer and use it in GitHub Desktop.
Provides a way to debounce events.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
// ReSharper disable MethodSupportsCancellation
/// <summary>
/// Provides a way to debounce events.
/// </summary>
public class Debouncer
{
private readonly ConcurrentDictionary<Delegate, CancellationTokenSource> _debounced = new ConcurrentDictionary<Delegate, CancellationTokenSource>();
/// <summary>
/// Debounces a method.
/// </summary>
/// <param name="timeout">The time to wait for other calls before the method is actually called.</param>
/// <param name="method">The method to debounce.</param>
public void Debounce(TimeSpan timeout, Action action)
{
Debounce(timeout, action, null);
}
/// <summary>
/// Debounces a method.
/// </summary>
/// <param name="timeout">The time to wait for other calls before the method is actually called.</param>
/// <param name="method">The method to debounce.</param>
/// <param name="args">The arguments of the method to debounce, if there are any.</param>
public async void Debounce(TimeSpan timeout, Delegate method, params object[] args)
{
try
{
if (_debounced.TryRemove(method, out var cts))
{
cts.Cancel();
}
var dispatchCancellation = new CancellationTokenSource();
_debounced.TryAdd(method, dispatchCancellation);
await Task
.Delay(timeout)
.ContinueWith(_ =>
{
if (!dispatchCancellation.IsCancellationRequested && _debounced.TryRemove(method, out var _))
method.DynamicInvoke(args);
});
dispatchCancellation.Dispose();
}
catch
{
// ignored
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment