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; } }
829200cookie-checkC# Throttle Function