public static ValueTask <IAsyncDisposable> Timer(IAsyncObserver <long> observer, DateTimeOffset dueTime, TimeSpan period, IAsyncScheduler scheduler) { if (period < TimeSpan.Zero) { throw new ArgumentOutOfRangeException(nameof(period)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } var tick = 0L; return(scheduler.ScheduleAsync(async ct => { if (ct.IsCancellationRequested) { return; } // TODO: Compensate for drift by adding stopwatch functionality. do { await observer.OnNextAsync(tick++).RendezVous(scheduler, ct); await scheduler.Delay(period, ct).RendezVous(scheduler, ct); } while (!ct.IsCancellationRequested); }, dueTime)); }
public static IAsyncObservable <int> ProduceSlowly(this IAsyncScheduler scheduler, params TimeSpan[] delays) { return(AsyncObservable.Range(0, delays.Length) .Select(async(i, ca) => { await scheduler.Delay(delays[i], ca).ConfigureAwait(false); return i; })); }
public static Task <IAsyncDisposable> Generate <TState, TResult>(IAsyncObserver <TResult> observer, TState initialState, Func <TState, Task <bool> > condition, Func <TState, Task <TState> > iterate, Func <TState, Task <TResult> > resultSelector, Func <TState, Task <DateTimeOffset> > timeSelector, IAsyncScheduler scheduler) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } if (condition == null) { throw new ArgumentNullException(nameof(condition)); } if (iterate == null) { throw new ArgumentNullException(nameof(iterate)); } if (resultSelector == null) { throw new ArgumentNullException(nameof(resultSelector)); } if (timeSelector == null) { throw new ArgumentNullException(nameof(timeSelector)); } if (scheduler == null) { throw new ArgumentNullException(nameof(scheduler)); } return(scheduler.ScheduleAsync(async ct => { var first = true; var state = initialState; while (!ct.IsCancellationRequested) { var hasResult = false; var result = default(TResult); var nextDue = default(DateTimeOffset); try { if (first) { first = false; } else { state = await iterate(state).RendezVous(scheduler, ct); } hasResult = await condition(state).RendezVous(scheduler, ct); if (hasResult) { result = await resultSelector(state).RendezVous(scheduler, ct); nextDue = await timeSelector(state).RendezVous(scheduler, ct); } } catch (Exception ex) { await observer.OnErrorAsync(ex).RendezVous(scheduler, ct); return; } if (hasResult) { await observer.OnNextAsync(result).RendezVous(scheduler, ct); } else { break; } await scheduler.Delay(nextDue).RendezVous(scheduler, ct); } if (!ct.IsCancellationRequested) { await observer.OnCompletedAsync().RendezVous(scheduler, ct); } })); }