C# Debounced Process Queue

Date: 2021-09-03
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();
	}
}
52710cookie-checkC# Debounced Process Queue