Table of Contents

AsyncDebouncer Class

Definition

Namespace
Bodu.Threading
Assembly
Bodu.Core.dll
Package
Bodu.Core 1.0.1
Source
AsyncDebouncer.Run.cs

Coalesces a rapid burst of triggers into a single asynchronous invocation that runs once a quiet period has elapsed since the most recent trigger.

public sealed class AsyncDebouncer : IDisposable
Inheritance
AsyncDebouncer
Implements
Inherited Members
Extension Methods

Examples

var debouncer = new AsyncDebouncer(
    TimeSpan.FromMilliseconds(300),
    async ct => await SaveAsync(ct));

// Called on every keystroke; SaveAsync runs once, 300 ms after typing stops.
textBox.TextChanged += (_, _) => debouncer.Invoke();

Remarks

Each call to Invoke() (re)starts a quiet timer of the configured delay. The callback runs only when the timer elapses with no intervening Invoke(), so a flurry of triggers results in a single execution. FlushAsync(CancellationToken) runs a pending invocation immediately and awaits any work in flight, and Cancel() discards a pending invocation and cancels any in-flight callback.

Execution policy. When a run becomes due while a previous callback is still running, behavior is governed by the configured AsyncDebouncerExecutionPolicy (defaulting to QueueOneTrailingRun). The default and DropWhileRunning never overlap callbacks; CancelAndRestart cancels and replaces the in-flight callback; and AllowOverlap permits concurrent callbacks.

Timing uses the supplied TimeProvider (defaulting to System), which allows deterministic testing with a controllable provider. Exceptions thrown by the callback (other than the cancellation triggered by Cancel(), Dispose(), or a restart) are surfaced through the CallbackFailed event rather than being silently lost; CurrentExecution exposes the most recently started callback task.

Constructors

AsyncDebouncer(TimeSpan, Func<CancellationToken, ValueTask>, AsyncDebouncerExecutionPolicy, TimeProvider?)

Initializes a new instance of the AsyncDebouncer class.

public AsyncDebouncer(TimeSpan delay, Func<CancellationToken, ValueTask> callback, AsyncDebouncerExecutionPolicy executionPolicy = AsyncDebouncerExecutionPolicy.QueueOneTrailingRun, TimeProvider? timeProvider = null)

Parameters

delay TimeSpan

The quiet period that must elapse after the last trigger before the callback runs.

callback Func<CancellationToken, ValueTask>

The asynchronous callback invoked when the quiet period elapses.

executionPolicy AsyncDebouncerExecutionPolicy

The policy governing behavior when a run becomes due while a callback is in flight.

timeProvider TimeProvider

The time provider used to schedule the delay, or null to use System.

Exceptions

ArgumentNullException

callback is null.

ArgumentOutOfRangeException

delay is negative, or executionPolicy is not a defined value.

Properties

CurrentExecution

Gets the most recently started callback task, if one is currently active.

public Task? CurrentExecution { get; }

Property Value

Task

The latest in-flight callback Task, or null when no run is currently active - either because none has started yet or because every started run has already completed and been removed from the active set.

ExecutionPolicy

Gets the execution policy that governs overlapping runs.

public AsyncDebouncerExecutionPolicy ExecutionPolicy { get; }

Property Value

AsyncDebouncerExecutionPolicy

The configured AsyncDebouncerExecutionPolicy.

Methods

Cancel()

Discards a pending invocation and cancels the token passed to any in-flight callback.

public void Cancel()

Examples

// Drop any queued invocation and signal in-flight callback work to stop.
debouncer.Cancel();

Exceptions

ObjectDisposedException

The debouncer has been disposed.

Dispose()

Releases the resources used by the debouncer, discarding any pending invocation and canceling any in-flight callbacks.

public void Dispose()

DrainAsync(CancellationToken)

Awaits all callback work currently in flight, including the trailing run queued under QueueOneTrailingRun.

public ValueTask DrainAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token used to cancel only this caller's wait.

Returns

ValueTask

A ValueTask that completes when no callback work remains in flight.

Remarks

Once the debouncer has been disposed this method returns immediately - it does not throw ObjectDisposedException - even when cooperatively-cancelled callbacks are still running their final iterations. Callers that must observe the end of that residual work should await the task obtained from CurrentExecution before disposal instead.

Exceptions

OperationCanceledException

cancellationToken was canceled before the work drained.

FlushAsync(CancellationToken)

Runs a pending invocation immediately, bypassing the remaining quiet period, and awaits any callback work in flight.

public ValueTask FlushAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token used to cancel only this caller's wait for the in-flight work to drain.

Returns

ValueTask

A ValueTask that completes when the triggered and in-flight callbacks have completed.

Examples

// Run the pending callback now instead of waiting out the quiet period (e.g. on shutdown).
await debouncer.FlushAsync();

Exceptions

ObjectDisposedException

The debouncer has been disposed.

OperationCanceledException

cancellationToken was canceled before the work drained.

Invoke()

Registers a trigger, (re)starting the quiet period after which the callback runs.

public void Invoke()

Exceptions

ObjectDisposedException

The debouncer has been disposed.

Events

CallbackFailed

Occurs when a callback invocation faults with an exception other than its own cancellation.

public event EventHandler<Exception>? CallbackFailed

Event Type

EventHandler<Exception>

Remarks

The handler runs outside the debouncer's internal gate on the thread that observed the failure.

Applies to

ProductVersions
.NET8, 10