Pause and Resume Subscription on cold IObservable

后端 未结 4 509
南笙
南笙 2020-12-03 03:45

Using Rx, I desire pause and resume functionality in the following code:

How to implement Pause() and Resume() ?

    static IDisposable _subscripti         


        
4条回答
  •  暖寄归人
    2020-12-03 04:23

    Here is my answer. I believe there may be a race condition around pause resume, however this can be mitigated by serializing all activity onto a scheduler. (favor Serializing over synchronizing).

    using System;
    using System.Reactive.Concurrency;
    using System.Reactive.Disposables;
    using System.Reactive.Linq;
    using System.Reactive.Subjects;
    using Microsoft.Reactive.Testing;
    using NUnit.Framework;
    
    namespace StackOverflow.Tests.Q7620182_PauseResume
    {
        [TestFixture]
        public class PauseAndResumeTests
        {
            [Test]
            public void Should_pause_and_resume()
            {
                //Arrange
                var scheduler = new TestScheduler();
    
                var isRunningTrigger = new BehaviorSubject(true);
                Action pause = () => isRunningTrigger.OnNext(false);
                Action resume = () => isRunningTrigger.OnNext(true);
    
                var source = scheduler.CreateHotObservable(
                    ReactiveTest.OnNext(0.1.Seconds(), 1),
                    ReactiveTest.OnNext(2.0.Seconds(), 2),
                    ReactiveTest.OnNext(4.0.Seconds(), 3),
                    ReactiveTest.OnNext(6.0.Seconds(), 4),
                    ReactiveTest.OnNext(8.0.Seconds(), 5));
    
                scheduler.Schedule(TimeSpan.FromSeconds(0.5), () => { pause(); });
                scheduler.Schedule(TimeSpan.FromSeconds(5.0), () => { resume(); });
    
    
    
                //Act
                var sut = Observable.Create>(o =>
                {
                    var current = source.Replay();
                    var connection = new SerialDisposable();
                    connection.Disposable = current.Connect();
    
                    return isRunningTrigger
                        .DistinctUntilChanged()
                        .Select(isRunning =>
                        {
                            if (isRunning)
                            {
                                    //Return the current replayed values.
                                    return current;
                            }
                            else
                            {
                                    //Disconnect and replace current.
                                    current = source.Replay();
                                    connection.Disposable = current.Connect();
                                    //yield silence until the next time we resume.
                                    return Observable.Never();
                            }
    
                        })
                        .Subscribe(o);
                }).Switch();
    
                var observer = scheduler.CreateObserver();
                using (sut.Subscribe(observer))
                {
                    scheduler.Start();
                }
    
                //Assert
                var expected = new[]
                {
                        ReactiveTest.OnNext(0.1.Seconds(), 1),
                        ReactiveTest.OnNext(5.0.Seconds(), 2),
                        ReactiveTest.OnNext(5.0.Seconds(), 3),
                        ReactiveTest.OnNext(6.0.Seconds(), 4),
                        ReactiveTest.OnNext(8.0.Seconds(), 5)
                    };
                CollectionAssert.AreEqual(expected, observer.Messages);
            }
        }
    }
    

提交回复
热议问题