Last active
July 7, 2022 13:49
-
-
Save cocowalla/5d181b82b9a986c6761585000901d1b8 to your computer and use it in GitHub Desktop.
Simple debounce
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace MyNamespace | |
{ | |
public class Debouncer : IDisposable | |
{ | |
private readonly CancellationTokenSource cts = new CancellationTokenSource(); | |
private readonly TimeSpan waitTime; | |
private int counter; | |
public Debouncer(TimeSpan? waitTime = null) | |
{ | |
this.waitTime = waitTime ?? TimeSpan.FromSeconds(3); | |
} | |
public void Debouce(Action action) | |
{ | |
var current = Interlocked.Increment(ref this.counter); | |
Task.Delay(this.waitTime).ContinueWith(task => | |
{ | |
// Is this the last task that was queued? | |
if (current == this.counter && !this.cts.IsCancellationRequested) | |
action(); | |
task.Dispose(); | |
}, this.cts.Token); | |
} | |
public void Dispose() | |
{ | |
this.cts.Cancel(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.Extensions.Configuration; | |
using Microsoft.Extensions.Primitives; | |
namespace MyNamespace | |
{ | |
public static class IConfigurationExtensions | |
{ | |
/// <summary> | |
/// Perform an action when configuration changes. Note this requires config sources to be added with | |
/// `reloadOnChange` enabled | |
/// </summary> | |
/// <param name="config">Configuration to watch for changes</param> | |
/// <param name="action">Action to perform when <paramref name="config"/> is changed</param> | |
public static void OnChange(this IConfiguration config, Action action) | |
{ | |
// IConfiguration's change detection is based on FileSystemWatcher, which will fire multiple change | |
// events for each change - Microsoft's code is buggy in that it doesn't bother to debounce/dedupe | |
// https://github.com/aspnet/AspNetCore/issues/2542 | |
var debouncer = new Debouncer(TimeSpan.FromSeconds(3)); | |
ChangeToken.OnChange<object>(config.GetReloadToken, _ => debouncer.Debouce(action), null); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
var config = new ConfigurationBuilder() | |
.AddJsonFile("appsettings.json", false, true) | |
.SetBasePath(Directory.GetCurrentDirectory()) | |
.Build(); | |
config.OnChange(() => | |
{ | |
// TODO: Config has been changed, do stuff here | |
}); | |
... |
Hopefully an async overload will make it into v7 later this year. If this is still important to you please upvote to help prioritise it? :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@cocowalla, @dazinator I landed here via dotnet/aspnetcore#2542. Thanks for setting me on the right path.
I use this async approach, using a hosted service. This is better as we don't have to run async-in-sync and blow up something accidentally.
Debouncer.cs
:ConfigWatcher.cs
:Startup.cs
:Works for me. Here's a related SO question with this code.