反应性 - 将可观察间隔与手动触发相结合

时间:2016-05-10 07:41:14

标签: c# system.reactive observable

我有Observable.Interval(TimeSpan.FromSeconds(1))和订阅者,每次发生间隔时都会检查数据库中的内容。但有时当我从DB那里检查​​时,我想立即执行另一次检查(再次呼叫该用户,因为我知道队列中有东西)。

我已经设法通过在订阅者方法中将Interval与while结合起来实现类似的功能:

 Observable              
.Interval(TimeSpan.FromSeconds(1))
.Sample(TimeSpan.FromSeconds(1)) //to avoid multiple 'stacked' intervals 
.Subscribe(RepeatAction);


private void RepeatAction(long _)
{
    bool wasSuccess;
    do
    {
        wasSuccess = CheckingInDB(); //Long operation
    } while (wasSuccess );
}

但是有可能用反应来实现这种行为吗?

1 个答案:

答案 0 :(得分:3)

是。这是可能的。

首先,你对Rx有一个误解。

如果您运行此代码:

void Main()
{
    Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .Sample(TimeSpan.FromSeconds(1.0))
        .Timestamp()
        .Subscribe(RepeatAction);
}

private void RepeatAction(Timestamped<long> _)
{
    Console.WriteLine(_.Timestamp);
    Thread.Sleep(10000);
}

你会得到这个结果:

2016/05/11 10:37:57 +00:00
2016/05/11 10:38:07 +00:00
2016/05/11 10:38:17 +00:00
2016/05/11 10:38:27 +00:00

您会看到生成的每个值之间的步数是10秒,而不是1. Interval运算符只是确保每个值之间的差距至少持续时间TimeSpan,但如果观察者需要更长的时间,那么持续时间就会变得与每个订阅者一样长。它没有排队值。

另一种看待它的方式是.Sample(TimeSpan.FromSeconds(1))没有做任何事情,因为.Interval(TimeSpan.FromSeconds(1.0))确保值之间的最小差距已经是1秒。

现在,使用纯粹的Rx运算符解决问题。试试这个:

var query =
    Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .Select(_ =>
            Observable
                .While(
                    () => CheckingInDB(),
                    Observable.Return(Unit.Default)))
        .Switch();

这将尝试每秒检查数据库,但是一旦它达到一个值,它会快速重复检查,直到它没有。然后等待1秒再试一次。