Dorssel.Utilities.Debounce 3.0.0

dotnet add package Dorssel.Utilities.Debounce --version 3.0.0                
NuGet\Install-Package Dorssel.Utilities.Debounce -Version 3.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dorssel.Utilities.Debounce" Version="3.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Dorssel.Utilities.Debounce --version 3.0.0                
#r "nuget: Dorssel.Utilities.Debounce, 3.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Dorssel.Utilities.Debounce as a Cake Addin
#addin nuget:?package=Dorssel.Utilities.Debounce&version=3.0.0

// Install Dorssel.Utilities.Debounce as a Cake Tool
#tool nuget:?package=Dorssel.Utilities.Debounce&version=3.0.0                

.NET event debouncer

Build CodeQL Lint REUSE status codecov NuGet

This library exposes a single object: an event debouncer. It can be used to "filter" or "buffer" multiple incoming events into one. It is also able to buffer attached event data for later usage at a performance cost. Common uses are:

  • Throttling how often the event handler is called.
  • Coalescing/debounce multiple events into one; the final event includes to total number of events received.
  • Serializing the event handler, such that it is not called re-entrant even if events are fired from multiple concurrent sources.
  • Spacing event handler calls, to give the CPU / disk / network some breathing room if events are arriving continuously.

Examples

auto-save

You want auto-save for your changing documents. Every key press alters the document, but not every key press should immediately lead to saving. Instead, the debouncer only fires when no new events are coming in within a configurable time window (such as when the user stops typing for 10 seconds). But simultaneously, the event should not be held off forever (such as when the user types continously). Therefore, the debouncer has a configurable maximum timeout after which the save event is no longer held back (for example, you want to auto-save no later than 5 minutes after the first change).

screen updates

You want your screen to reflect any changes in the underlying data (for example, via INotifyPropertyChanged). But if changes are happening a million times a second, you want the screen to only update a maximum of 50 times per second instead of claiming the CPU entirely. You configure the debounce window to 5 ms, such that any changes are displayed promptly (while holding off any updates if new event arrive within 5 ms of the previous event); and the timeout and handler spacing to 20 ms, such that the screen is updated 50 times a second if needed.

server-side pushes

Your website server wants to push any update of internal state to the client, but always at least 100 ms apart from any previous push. You could configure the debounce window and spacing to 100 ms, and the timeout to 1 s. If changes are continuously arriving (spaced less than 100 ms, within the debounce window), then the push happens every second (the timeout value). But if changes are sporadic, then they will be pushed after the initial timeout window of 100 ms for "snappiness". Finally, the debouncer will wait at least 100 ms (the spacer value) after the return of the previous handler, such that the network IO in the handler itself is given a bit of rest every time.

batch processing of data

You listen on a stream that fires a lot of events with data attached. You would like to space out the processing of these events in time, processing them in batches. By using the generic version of the Debouncer, it is possible to trigger events with data attached. Retrieve the list of original triggered data by accessing the TriggerData property of the DebouncedEventArgs. Multiple data types are supported as long as they have a common base class, such as EventArgs for compatibility with .NET events.

Performance

The library was written with performance in mind. The Trigger function (to indicate that a source event has arrived) can easily handle tens of millions of calls per second, coming in from multiple threads.

Once configured, the debouncer works without object allocation while debouncing.

When triggering the debouncer with data attached, it comes with a significant performance cost because of memory allocations and locking.

Versatility

The library targets netstandard2.0 and is compiled for AnyCPU.

The public API uses the interface design patern, which allows 100% code coverage testing with mocking (even for edge cases that will never occur in real life).

NuGet package

The released NuGet package and the .NET assemblies contained therein have the following properties:

Code Examples

The repository contains two examples:

  • A Blazor server-side push example that demonstrates the performance of the library.

  • An example that demonstrates how you can get 100% code coverage for classes that use the debouncer.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.0.0 81 1/22/2025
2.0.0 409 6/22/2024
1.0.0 204 1/9/2024