public IDisposable SchedulePeriodically(Action action, TimeSpan initialDelay, TimeSpan period) { MultipleAssignmentDisposable inner = new MultipleAssignmentDisposable(); MultipleAssignmentDisposable outer = new MultipleAssignmentDisposable(inner); if (tasks.Add(outer)) { IDisposable cancel = new ActionWeakDisposable(() => tasks.Remove(outer)); long startTime = NowUtc() + (long)initialDelay.TotalMilliseconds; long periodMillis = (long)period.TotalMilliseconds; long[] count = new long[1]; Action nextAction = null; nextAction = () => { if (!outer.IsDisposed()) { action(); long now = NowUtc(); long c = ++count[0]; long next = startTime + c * periodMillis; long toDelay = Math.Max(0, next - startTime); outer.Set(Schedule(nextAction, TimeSpan.FromMilliseconds(toDelay))); } }; IDisposable f = Task.Delay(initialDelay).ContinueWith(a => { if (!outer.IsDisposed()) { outer.Set(Schedule(nextAction)); } }); inner.Set(f); return(cancel); } return(EmptyDisposable.Instance); }
public IDisposable Schedule(Action action, TimeSpan delay) { MultipleAssignmentDisposable inner = new MultipleAssignmentDisposable(); MultipleAssignmentDisposable outer = new MultipleAssignmentDisposable(inner); if (tasks.Add(outer)) { IDisposable cancel = new ActionWeakDisposable(() => tasks.Remove(outer)); IDisposable f = Task.Delay(delay).ContinueWith(a => { if (!outer.IsDisposed()) { outer.Set(Schedule(action)); } }); inner.Set(f); return(cancel); } return(EmptyDisposable.Instance); }