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