<PackageReference Include="System.Reactive" Version="6.0.0-preview.16" />

VirtualTimeSchedulerBase<TAbsolute, TRelative>

public abstract class VirtualTimeSchedulerBase<TAbsolute, TRelative> : IScheduler, IServiceProvider, IStopwatchProvider where TAbsolute : IComparable<TAbsolute>
Base class for virtual time schedulers.
using System.Collections.Generic; using System.Globalization; using System.Runtime.CompilerServices; namespace System.Reactive.Concurrency { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public abstract class VirtualTimeSchedulerBase<[System.Runtime.CompilerServices.Nullable(0)] TAbsolute, [System.Runtime.CompilerServices.Nullable(2)] TRelative> : IScheduler, IServiceProvider, IStopwatchProvider where TAbsolute : IComparable<TAbsolute> { [System.Runtime.CompilerServices.NullableContext(0)] private sealed class VirtualTimeStopwatch : IStopwatch { [System.Runtime.CompilerServices.Nullable(1)] private readonly VirtualTimeSchedulerBase<TAbsolute, TRelative> _parent; private readonly DateTimeOffset _start; public TimeSpan Elapsed => _parent.ClockToDateTimeOffset() - _start; [System.Runtime.CompilerServices.NullableContext(1)] public VirtualTimeStopwatch(VirtualTimeSchedulerBase<TAbsolute, TRelative> parent, DateTimeOffset start) { _parent = parent; _start = start; } } public bool IsEnabled { get; set; } protected IComparer<TAbsolute> Comparer { get; } public TAbsolute Clock { get; set; } public DateTimeOffset Now => ToDateTimeOffset(Clock); protected VirtualTimeSchedulerBase() : this(default(TAbsolute), (IComparer<TAbsolute>)Comparer<TAbsolute>.Default) { } protected VirtualTimeSchedulerBase(TAbsolute initialClock, IComparer<TAbsolute> comparer) { Clock = initialClock; if (comparer == null) throw new ArgumentNullException("comparer"); Comparer = comparer; } protected abstract TAbsolute Add(TAbsolute absolute, TRelative relative); protected abstract DateTimeOffset ToDateTimeOffset(TAbsolute absolute); protected abstract TRelative ToRelative(TimeSpan timeSpan); public abstract IDisposable ScheduleAbsolute<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, TAbsolute dueTime, Func<IScheduler, TState, IDisposable> action); public IDisposable ScheduleRelative<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, TRelative dueTime, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); TAbsolute dueTime2 = this.Add(this.Clock, dueTime); return ScheduleAbsolute(state, dueTime2, action); } public IDisposable Schedule<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); return ScheduleAbsolute(state, this.Clock, action); } public IDisposable Schedule<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); return ScheduleRelative(state, this.ToRelative(dueTime), action); } public IDisposable Schedule<[System.Runtime.CompilerServices.Nullable(2)] TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); return ScheduleRelative(state, this.ToRelative(dueTime - this.Now), action); } public void Start() { if (!IsEnabled) { IsEnabled = true; do { IScheduledItem<TAbsolute> next = GetNext(); if (next != null) { if (Comparer.Compare(next.DueTime, Clock) > 0) Clock = next.DueTime; next.Invoke(); } else IsEnabled = false; } while (IsEnabled); } } public void Stop() { IsEnabled = false; } public void AdvanceTo(TAbsolute time) { int num = Comparer.Compare(time, Clock); if (num < 0) throw new ArgumentOutOfRangeException("time"); if (num != 0) { if (IsEnabled) throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.CANT_ADVANCE_WHILE_RUNNING, "AdvanceTo")); IsEnabled = true; do { IScheduledItem<TAbsolute> next = GetNext(); if (next != null && Comparer.Compare(next.DueTime, time) <= 0) { if (Comparer.Compare(next.DueTime, Clock) > 0) Clock = next.DueTime; next.Invoke(); } else IsEnabled = false; } while (IsEnabled); Clock = time; } } public void AdvanceBy(TRelative time) { TAbsolute val = Add(Clock, time); int num = Comparer.Compare(val, Clock); if (num < 0) throw new ArgumentOutOfRangeException("time"); if (num != 0) { if (IsEnabled) throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Strings_Linq.CANT_ADVANCE_WHILE_RUNNING, "AdvanceBy")); AdvanceTo(val); } } public void Sleep(TRelative time) { TAbsolute val = Add(Clock, time); if (Comparer.Compare(val, Clock) < 0) throw new ArgumentOutOfRangeException("time"); Clock = val; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] protected abstract IScheduledItem<TAbsolute> GetNext(); [return: System.Runtime.CompilerServices.Nullable(2)] object IServiceProvider.GetService(Type serviceType) { return GetService(serviceType); } [return: System.Runtime.CompilerServices.Nullable(2)] protected virtual object GetService(Type serviceType) { if (serviceType == typeof(IStopwatchProvider)) return this; return null; } public IStopwatch StartStopwatch() { DateTimeOffset start = ClockToDateTimeOffset(); return new VirtualTimeStopwatch(this, start); } private DateTimeOffset ClockToDateTimeOffset() { return ToDateTimeOffset(Clock); } } }