< Summary

Information
Class: MyNet.Utilities.Threading.Debouncer
Assembly: MyNet.Utilities
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Utilities/Threading/Debouncer.cs
Tag: 323_28699572109
Line coverage
96%
Covered lines: 24
Uncovered lines: 1
Coverable lines: 25
Total lines: 85
Line coverage: 96%
Branch coverage
50%
Covered branches: 2
Total branches: 4
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Schedule(...)100%11100%
Fire()50%22100%
Dispose()50%2287.5%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Utilities/Threading/Debouncer.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="Debouncer.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Threading;
 9
 10namespace MyNet.Utilities.Threading;
 11
 12/// <summary>
 13/// Coalesces rapid repeated signals into a single callback after a quiet period.
 14/// </summary>
 15internal sealed class Debouncer : IDisposable
 16{
 317    private readonly Lock _lock = new();
 18    private readonly Timer _timer;
 19    private readonly int _delayMilliseconds;
 20    private Action? _pending;
 21    private bool _disposed;
 22
 23    /// <summary>
 24    /// Initializes a new instance of the <see cref="Debouncer"/> class with the specified delay in milliseconds. The de
 25    /// </summary>
 26    /// <param name="delayMilliseconds">The delay in milliseconds.</param>
 27    /// <exception cref="ArgumentOutOfRangeException">Thrown if the delay is negative.</exception>
 28    public Debouncer(int delayMilliseconds)
 29    {
 330        ArgumentOutOfRangeException.ThrowIfNegative(delayMilliseconds);
 331        _delayMilliseconds = delayMilliseconds;
 332        _timer = new(static s => ((Debouncer)s!).Fire(), this, Timeout.Infinite, Timeout.Infinite);
 333    }
 34
 35    /// <summary>
 36    /// Schedules the specified action to be invoked after the delay. If called again before the delay elapses, the prev
 37    /// </summary>
 38    /// <param name="action">The action to be invoked after the delay.</param>
 39    /// <exception cref="ObjectDisposedException">Thrown if the debouncer has been disposed.</exception>
 40    /// <exception cref="ArgumentNullException">Thrown if the action is null.</exception>
 41    public void Schedule(Action action)
 42    {
 943        ObjectDisposedException.ThrowIf(_disposed, this);
 944        ArgumentNullException.ThrowIfNull(action);
 45
 46        lock (_lock)
 47        {
 948            _pending = action;
 949            _ = _timer.Change(_delayMilliseconds, Timeout.Infinite);
 950        }
 951    }
 52
 53    /// <summary>
 54    /// Invokes the pending action if any, and clears it. This method is called by the timer callback when the delay ela
 55    /// </summary>
 56    private void Fire()
 357    {
 58        Action? action;
 59
 60        lock (_lock)
 61        {
 362            action = _pending;
 363            _pending = null;
 364        }
 65
 366        action?.Invoke();
 367    }
 68
 69    /// <summary>
 70    /// Disposes the debouncer, preventing any pending or future scheduled actions from being invoked.
 71    /// </summary>
 72    public void Dispose()
 373    {
 74        lock (_lock)
 75        {
 376            if (_disposed)
 077                return;
 78
 379            _disposed = true;
 380            _pending = null;
 381            _timer.Dispose();
 382        }
 383    }
 84}
 85