public void SubProgressCancellationTokenSource()
        {
            IAmbientProgress progress = AmbientProgressService.Progress;

            progress?.ResetCancellation(); // make a new cancellation in case the source was canceled in this execution context during a previous test
            using (progress?.TrackPart(0.0f, 1.0f))
            {
                IAmbientProgress subprogress = AmbientProgressService.Progress;
                using (AmbientClock.Pause())
                {
                    subprogress?.ResetCancellation(TimeSpan.FromMilliseconds(100));
                    AmbientCancellationTokenSource tokenSource = subprogress?.CancellationTokenSource;
                    Assert.IsNotNull(tokenSource);
                    Assert.IsFalse(tokenSource?.IsCancellationRequested ?? true);
                    Assert.AreEqual(tokenSource?.Token, subprogress?.CancellationToken);
                    AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100));
                    Assert.IsTrue(tokenSource?.IsCancellationRequested ?? false);
                    Assert.AreEqual(tokenSource?.Token, subprogress?.CancellationToken);
                    Assert.IsTrue(subprogress?.CancellationToken.IsCancellationRequested ?? false);

                    subprogress?.ResetCancellation(null);
                    AmbientCancellationTokenSource newTokenSource = subprogress?.CancellationTokenSource;
                    Assert.IsNotNull(newTokenSource);
                    Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true);
                    Assert.AreEqual(newTokenSource?.Token, subprogress?.CancellationToken);
                    AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100));
                    Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true);
                    Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false);
                    Assert.AreEqual(newTokenSource?.Token, subprogress?.CancellationToken);
                    Assert.IsFalse(subprogress?.CancellationToken.IsCancellationRequested ?? true);

                    subprogress?.Update(0.5f);
                    subprogress?.ThrowIfCancelled();
                }
            }
        }
        public void CancellationTokenSource()
        {
            IAmbientProgress progress = AmbientProgressService.Progress;

            progress?.ResetCancellation(); // make a new cancellation in case the source was canceled in this execution context during a previous test
            using (AmbientClock.Pause())
            {
                progress?.ResetCancellation(TimeSpan.FromMilliseconds(102));
                using (AmbientCancellationTokenSource tokenSource = progress?.CancellationTokenSource)
                {
                    Assert.IsNotNull(tokenSource);
                    Assert.IsFalse(tokenSource?.IsCancellationRequested ?? true);
                    Assert.AreEqual(tokenSource?.Token, progress?.CancellationToken);
                    AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(111));
                    Assert.IsTrue(tokenSource?.IsCancellationRequested ?? false);
                    Assert.AreEqual(tokenSource?.Token, progress?.CancellationToken);
                    Assert.IsTrue(progress?.CancellationToken.IsCancellationRequested ?? false);

                    progress?.ResetCancellation();
                    AmbientCancellationTokenSource newTokenSource = progress?.CancellationTokenSource;
                    Assert.IsNotNull(newTokenSource);
                    Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true);
                    Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken);
                    AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(100));
                    Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true);
                    Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false);
                    Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken);
                    Assert.IsFalse(progress?.CancellationToken.IsCancellationRequested ?? true);

                    progress?.Update(0.5f);
                    progress?.ThrowIfCancelled();

                    using (CancellationTokenSource ts = new CancellationTokenSource())
                    {
                        progress?.ResetCancellation(ts);
                        newTokenSource = progress?.CancellationTokenSource;
                        Assert.IsNotNull(newTokenSource);
                        Assert.IsFalse(newTokenSource?.IsCancellationRequested ?? true);
                        Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken);
                        Assert.IsTrue(newTokenSource?.Token.CanBeCanceled ?? false);
                        ts.Cancel();
                        Assert.IsTrue(newTokenSource?.IsCancellationRequested ?? false);
                        Assert.AreEqual(newTokenSource?.Token, progress?.CancellationToken);
                        Assert.IsTrue(progress?.CancellationToken.IsCancellationRequested ?? false);
                    }
                    using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource(null, null))
                    {
                        Assert.IsFalse(ts.IsCancellationRequested);
                        Assert.IsFalse(ts.Token.IsCancellationRequested);

                        ts.Dispose();

                        Assert.IsTrue(ts.IsCancellationRequested);
                        Assert.IsTrue(ts.Token.IsCancellationRequested);
                    }
                    using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource(null, TimeSpan.FromMilliseconds(int.MaxValue)))
                    {
                        Assert.IsFalse(ts.IsCancellationRequested);     // theoretically, this could fail if this part of the test takes more than 30 days to execute
                        Assert.IsFalse(ts.Token.IsCancellationRequested);

                        ts.Dispose();

                        Assert.IsTrue(ts.IsCancellationRequested);
                        Assert.IsTrue(ts.Token.IsCancellationRequested);
                    }
                    AmbientCancellationTokenSource dispose;
                    using (AmbientCancellationTokenSource ts = new AmbientCancellationTokenSource())
                    {
                        dispose = ts;
                    }
                    dispose.CancelAfter(1);
                    System.Threading.Thread.Sleep(500);
                    AmbientClock.SkipAhead(TimeSpan.FromMilliseconds(500));
                    dispose.Cancel(false);
                }
            }
        }