C# Throttle Function

Date: 2024-02-19
public class Throttle<T>
{
    private readonly Func<Task<T>> _initialFn;
    private readonly TimeSpan _throttleTime;
    private TaskCompletionSource<T> _tcs;
    private DateTime _lastExecutionTime;
    private readonly object _lock = new object();

    public Throttle(TimeSpan throttleTime, Func<Task<T>> initialFn)
    {
        _initialFn = initialFn ?? throw new ArgumentNullException(nameof(initialFn));
        _throttleTime = throttleTime;
        _tcs = new TaskCompletionSource<T>();
        _lastExecutionTime = DateTime.MinValue;
    }

    private bool IsThrottleTimeElapsed()
    {
        return DateTime.UtcNow - _lastExecutionTime >= _throttleTime;
    }

    public void ClearLastExecutionTime()
    {
        lock (_lock)
        {
            _lastExecutionTime = DateTime.MinValue;
        }
    }
    private async Task<T> ExecuteInitialFunctionAsync()
    {
        try
        {
            var result = await _initialFn();
            _tcs.TrySetResult(result);
        }
        catch (Exception ex)
        {
            _tcs.TrySetException(ex);
        }

        return await _tcs.Task;
    }

    public Task<T> ExecuteAsync()
    {
        Task<T> taskToAwait;

        lock (_lock)
        {
            if (!IsThrottleTimeElapsed())
            {
                taskToAwait = _tcs.Task;
            }
            else
            {
                _tcs = new TaskCompletionSource<T>();
                _lastExecutionTime = DateTime.UtcNow;
                taskToAwait = ExecuteInitialFunctionAsync();
            }
        }

        return taskToAwait;
    }
}
82920cookie-checkC# Throttle Function