Rx缓存 - 重播运算符清除

时间:2016-05-18 15:28:35

标签: c# .net system.reactive

我在这里使用以下代码 - 在清除“重播缓存”时对我来说是一个问题

https://gist.github.com/leeoades/4115023

如果我更改以下调用和代码,我发现重播中存在错误,即它永远不会被清除。有人可以帮忙纠正这个问题吗?

private Cache<string> GetCalculator()
    {
        var calculation = Observable.Create<string>(o =>
        {
            _calculationStartedCount++;

            return Observable.Timer(_calculationDuration, _testScheduler)
                             .Select(_ => "Hello World!" + _calculationStartedCount) // suffixed the string with count to test the behaviour of Replay clearing
                             .Subscribe(o);
        });

        return new Cache<string>(calculation);
    }

[Test]
    public void After_Calling_GetResult_Calling_ClearResult_and_GetResult_should_perform_calculation_again()
    {
        // ARRANGE
        var calculator = GetCalculator();

        calculator.GetValue().Subscribe();
        _testScheduler.Start();

        // ACT
        calculator.Clear();

        string result = null;
        calculator.GetValue().Subscribe(r => result = r);
        _testScheduler.Start();

        // ASSERT
        Assert.That(_calculationStartedCount, Is.EqualTo(2));
        Assert.That(result, Is.EqualTo("Hello World!2")); // always returns Hello World!1 and not Hello World!2
        Assert.IsNotNull(result);
    }

2 个答案:

答案 0 :(得分:2)

问题是一个微妙的问题。源序列Timer在发出事件后完成,该事件又调用由OnCompleted创建的内部ReplaySubject上的Replay。当Subject完成后,即使显示新的Observable,它也不再接受任何新值。

当您重新订阅它再次执行的基础Observable时,但无法重新启动Subject,因此您的新Observer只能在ReplaySubject之前收到最新值{1}}已完成。

最简单的解决方案可能就是永远不要让源流完成(未经测试):

    public Cache(IObservable<T> source)
    {
        //Not sure why you are wrapping this in an Observable.create
        _source = source.Concat(Observable.Never())
                            .Replay(1, Scheduler.Immediate);
    }

答案 1 :(得分:0)

此处针对类似问题的解决方案(How can i clear the buffer on a ReplaySubject?)是否为您提供了所需的功能?