public async Task <T> Start() { try { await debouncedActionInvokeLocker.WaitAsync(processCancellationToken); if (State != ProcessingDebounceState.NotYetStarted) { throw new InvalidOperationException("Debounce process has been already started"); } stopwatch.Start(); State = ProcessingDebounceState.Running; } finally { debouncedActionInvokeLocker.Release(); } await Task.Delay(TimeSpan.FromMilliseconds(interval), processCancellationToken); try { await debouncedActionInvokeLocker.WaitAsync(processCancellationToken); stop(); return(await debouncedAction()); } finally { debouncedActionInvokeLocker.Release(); } }
/// <param name="interval">The interval in milliseconds.</param> /// <param name="debouncedAction">The function gets executed after interval</param> public ProcessingDebounce(long interval, Func <Task <T> > debouncedAction) { stopwatch = new Stopwatch(); delayCancellationTokenSource = new CancellationTokenSource(); processCancellationToken = delayCancellationTokenSource.Token; debouncedActionInvokeLocker = new SemaphoreSlim(1); State = ProcessingDebounceState.NotYetStarted; this.debouncedAction = debouncedAction; this.interval = interval; }
private void stop() { if (State == ProcessingDebounceState.Stopped || State == ProcessingDebounceState.Canceled) { return; } stopwatch.Stop(); State = ProcessingDebounceState.Stopped; }
public async Task TryCancel() { await debouncedActionInvokeLocker.WaitAsync(); try { if (State == ProcessingDebounceState.Stopped || State == ProcessingDebounceState.Canceled) { return; } if (stopwatch.ElapsedMilliseconds < interval) { stop(); delayCancellationTokenSource.Cancel(); State = ProcessingDebounceState.Canceled; } } finally { debouncedActionInvokeLocker.Release(); } }