ThrottleDebounce 2.0.0-SNAPSHOT

This is a prerelease version of ThrottleDebounce.
There is a newer version of this package available.
See the version list below for details.
dotnet add package ThrottleDebounce --version 2.0.0-SNAPSHOT
NuGet\Install-Package ThrottleDebounce -Version 2.0.0-SNAPSHOT
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="ThrottleDebounce" Version="2.0.0-SNAPSHOT" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ThrottleDebounce --version 2.0.0-SNAPSHOT
#r "nuget: ThrottleDebounce, 2.0.0-SNAPSHOT"
#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 ThrottleDebounce as a Cake Addin
#addin nuget:?package=ThrottleDebounce&version=2.0.0-SNAPSHOT&prerelease

// Install ThrottleDebounce as a Cake Tool
#tool nuget:?package=ThrottleDebounce&version=2.0.0-SNAPSHOT&prerelease

ThrottleDebounce

Nuget GitHub Workflow Status Coveralls

Rate limit your actions and funcs by throttling and debouncing them.

This is a .NET library that lets you rate-limit functions so they are only executed at most once in a given interval, even if they are invoked multiple times in that interval.

Installation

This package is available on NuGet Gallery.

Install-Package ThrottleDebounce
dotnet add package ThrottleDebounce

It targets .NET Standard 2.0 and .NET Framework 4.0, so it should be compatible with many runtimes.

Usage

Action originalAction;
Func<int> originalFunc;

TimeSpan wait = TimeSpan.FromMilliseconds(50);
using RateLimitedAction throttledAction = Throttler.Throttle(originalAction, wait, leading: true, trailing: true);
using RateLimitedFunc<int> debouncedFunc = Debouncer.Debounce(originalFunc, wait, leading: false, trailing: true);

throttledAction.Invoke();
int? result = debouncedFunc.Invoke();
  1. Call Throttler.Throttle() to throttle your delegate, or Debouncer.Debounce() to debounce it. Pass
    1. Action action/Func func — your delegate to rate-limit
    2. TimeSpan wait — how long to wait between executions
    3. bool leadingtrue if the first invocation should be executed immediately, or false if it should be queued. Optional, defaults to true for throttling and false for debouncing.
    4. bool trailingtrue if subsequent invocations in the waiting period should be enqueued for later execution once the waiting interval is over, or false if they should be discarded. Optional, defaults to true.
  2. Call the resulting RateLimitedAction/RateLimitedFunc object's Invoke() method to enqueue an invocation.
    • RateLimitedFunc.Invoke will return default (e.g. null) if leading is false and the rate-limited Func has not been executed before. Otherwise, it will return the Func's most recent return value.
  3. Your delegate will be executed at the desired rate.
  4. Optionally call the RateLimitedAction/RateLimitedFunc object's Dispose() method to prevent all queued executions from running when you are done.

Understanding throttling and debouncing

Summary

Throttling and debouncing both restrict a function to not execute too often, no matter how frequently you invoke it.

This is useful if the function is invoked very frequently, like whenever the mouse moves, but you don't want to it to run every single time the pointer moves 1 pixel, because the function is expensive, such as rendering a user interface.

Throttling allows the function to still be executed periodically, even with a constant stream of invocations.

Debouncing prevents the function from being executed at all until it hasn't been invoked for a while.

An invocation can result in at most one execution. For example, if both leading and trailing are true, one single invocation will execute once on the leading edge and not on the trailing edge.

Diagram

Strategies for Rate-Limiting

Lodash documentation

Article and demo

Debouncing and Throttling Explained Through Examples by David Corbacho

Examples

Throttle an action to execute at most every 1 second

Action throttled = Throttler.Throttle(() => Console.WriteLine("hi"), TimeSpan.FromSeconds(1)).Invoke;

throttled(); //logs at 0s
throttled(); //logs at 1s
Thread.Sleep(1000);
throttled(); //logs at 2s

Debounce a function to execute after no invocations for 200 milliseconds

Func<double, double, double> debounced = Debouncer.Debounce((double x, double y) => Math.Sqrt(x * x + y * y),
    TimeSpan.FromMilliseconds(200)).Invoke;

double? result;
result = debounced(1, 1); //never runs
result = debounced(2, 2); //never runs
result = debounced(3, 4); //runs at 200ms

Canceling a rate-limited action so any queued executions won't run

RateLimitedAction rateLimited = Throttler.Throttle(() => Console.WriteLine("hello"), TimeSpan.FromSeconds(1));

rateLimited.Invoke(); //runs at 0s
rateLimited.Dispose();
rateLimited.Invoke(); //never runs

Save a WPF window's position to the registry at most every 1 second

static void SaveWindowLocation(double x, double y) => Registry.SetValue(@"HKEY_CURRENT_USER\Software\My Program", 
    "Window Location", $"{x},{y}");

Action<double, double> saveWindowLocationThrottled = Throttler.Throttle<double, double>(saveWindowLocation, 
    TimeSpan.FromSeconds(1)).Invoke;

LocationChanged += (sender, args) => SaveWindowLocationThrottled(Left, Top);

Prevent accidental double-clicks on a WPF button

public MainWindow(){
    InitializeComponent();

    Action<object, RoutedEventArgs> onButtonClickDebounced = Debouncer.Debounce<object, RoutedEventArgs>(
        OnButtonClick, TimeSpan.FromMilliseconds(40), true, false).Invoke;

    MyButton.Click += new RoutedEventHandler(onButtonClickDebounced);
}

private void OnButtonClick(object sender, RoutedEventArgs e) {
    MessageBox.Show("Button clicked");
}
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 was computed.  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. 
.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 net40 is compatible.  net403 was computed.  net45 was computed.  net451 was computed.  net452 was computed.  net46 was computed.  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.
  • .NETFramework 4.0

    • No dependencies.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ThrottleDebounce:

Package Downloads
Elsa.Studio.Core

Core Elsa Studio services.

Elsa.DropIns

Provides drop-in features for Elsa workflows.

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on ThrottleDebounce:

Repository Stars
elsa-workflows/elsa-core
A .NET workflows library
elsa-workflows/elsa-studio
A modular, extensible dashboard application framework
Version Downloads Last updated
2.0.0 44,152 7/8/2022
2.0.0-SNAPSHOT-2 126 7/8/2022
2.0.0-SNAPSHOT 138 6/29/2022
1.0.3 54,073 9/11/2020
1.0.2 999 11/15/2019