ReactiveX自动取消定时器

时间:2016-08-22 15:58:20

标签: reactive-programming reactivex

我想创建一个表单的扩展方法:

IObservable<bool> CancellableTimer( this IObservable source, TimeSpan delay )
{
...
}

产生一个序列,当源是,该序列始终为false,但是当源序列在延迟定义的时间段内保持为真时,它将变为真,t:

source: 0---1---------0--1-0-1-0-1-0-1----------0
            t------>                 t------> 
result: 0----------1--0---------------------1---0

我确信必须有一种方法可以使用Rx原语来实现这一点,但我是Rx的新手并且无法理解它。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

好的,这就是我想出来的。我还将方法重命名为AsymetricDelay(),因为它似乎是一个更合适的名称:

    static public IObservable<bool> AsymetricDelay(this IObservable<bool> source, TimeSpan delay, IScheduler scheduler)
    {
        var distinct = source.DistinctUntilChanged();
        return distinct.
            Throttle(delay, scheduler) // Delay both trues and falses
            .Where(x => x)             // But we only want trues to be delayed
            .Merge(                   // Merge the trues with...
                distinct.Where(x=>!x) // non delayed falses
            )
            .DistinctUntilChanged(); // Get rid of any repeated values

    }

这是一个确认其运作的单元测试:

    [Fact]
    public static void Test_AsymetricDelay()
    {
        var scheduler = new TestScheduler();

        var xs = scheduler.CreateHotObservable(
            new Recorded<Notification<bool>>(10000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(60000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(70000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(80000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(100000000, Notification.CreateOnCompleted<bool>())
        );

        var dest = xs.DelayOn( TimeSpan.FromSeconds(2), scheduler);

        var testObserver = scheduler.Start(
            () => dest,            
            0,
            0,
            TimeSpan.FromSeconds(10).Ticks);


        testObserver.Messages.AssertEqual(
            new Recorded<Notification<bool>>(30000000, Notification.CreateOnNext(true)),
            new Recorded<Notification<bool>>(60000000, Notification.CreateOnNext(false)),
            new Recorded<Notification<bool>>(100000000, Notification.CreateOnCompleted<bool>())

        );
    }