public class DebouncedProcessQueue<T>
{
private readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
private readonly Debouncer debouncer;
private readonly Action<IEnumerable<T>> processAction;
private readonly int flushAfterQueueCount;
public DebouncedProcessQueue(Action<IEnumerable<T>> processAction, TimeSpan debounceTime, int flushAfterQueueCount = 50)
{
debouncer = new Debouncer(debounceTime, ProcessQueue);
this.processAction = processAction;
this.flushAfterQueueCount = flushAfterQueueCount;
}
private void ProcessQueue()
{
var items = new List<T>();
while (!queue.IsEmpty)
{
if (queue.TryDequeue(out var item))
items.Add(item);
}
if (items.Count == 0) return;
processAction(items);
}
public void Enqueue(T item)
{
queue.Enqueue(item);
if (queue.Count > flushAfterQueueCount)
debouncer.Flush();
else
debouncer.Debounce();
}
public void Flush() => debouncer.Flush();
}
public class Debouncer
{
public Debouncer(TimeSpan interval, Action action)
{
_interval = interval;
_action = action;
}
private volatile Timer _timer;
private readonly TimeSpan _interval;
private readonly Action _action;
public void Debounce()
{
_timer?.Dispose();
_timer = new Timer((state) =>
{
_action?.Invoke();
_timer?.Dispose();
}, null, (int)_interval.TotalMilliseconds, -1);
}
public void Flush()
{
_timer?.Dispose();
_action?.Invoke();
}
}
527110cookie-checkC# Debounced Process Queue