private async Task WorkerRoutine(CancellationToken token) { if (delayFirstIteration) { await DelaySafe(period(), token).ConfigureAwait(false); } while (!token.IsCancellationRequested) { var budget = TimeBudget.StartNew(period(), TimeSpan.FromMilliseconds(1)); try { await action(token, budget.Remaining).ConfigureAwait(false); } catch (OperationCanceledException e) when(e.CancellationToken == token && token.IsCancellationRequested) { return; } catch (Exception error) { errorHandler(error); } await DelaySafe(budget.Remaining, token).ConfigureAwait(false); } }
public PeriodicalAction( [NotNull] Action <TimeSpan> action, [NotNull] Action <Exception> errorHandler, [NotNull] Func <TimeSpan> period, bool delayFirstIteration = false) { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (period == null) { throw new ArgumentNullException(nameof(period)); } this.errorHandler = errorHandler ?? throw new ArgumentNullException(nameof(errorHandler)); stopEvent = new AutoResetEvent(false); workerRoutine = () => { if (delayFirstIteration) { stopEvent.WaitOne(period()); } while (IsRunning) { var actionBudget = TimeBudget.StartNew(period()); try { action(actionBudget.Remaining); } catch (Exception error) { errorHandler(error); } stopEvent.WaitOne(actionBudget.Remaining); } }; }