如何随着时间动态延迟可观察

泰勒·汉德利

我目前拥有一项功能,用户Timer()可以立即触发一个可观察对象,然后每隔x毫秒触发一次。

HoldPayloads = Observable.Merge(
    EnumeratedSymbolKeys.Select(
        o => Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
            h => o.PreviewMouseLeftButtonDown += h,
            h => o.PreviewMouseLeftButtonDown -= h)
            .Select(_ => Observable.Timer(DateTimeOffset.Now, TimeSpan.FromMilliseconds(o.Frequency))
            .TakeUntil(Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => o.PreviewMouseLeftButtonUp += h,
                h => o.PreviewMouseLeftButtonUp -= h)))
                .Switch()
                .Select(_ => o.Payload)));

我想要的是,单击按钮后立即出现可观察到的火,然后经过较长的初始延迟后,开始以更快的间隔或逐渐减小的间隔重复到一个极限,如下所示:

--x------x--x--x--x--x--x-->

要么

--x------x----x---x--x-x-x->

我试图Delay()结合使用Scan()来生成指数较低的值,以延迟但无法正常工作。我在正确的轨道上吗?还有更好的方法来做这样的事情吗?

使用Shlomo的答案修订的代码:

HoldPayloads = Observable.Merge(
EnumeratedSymbolKeys.Select(
    o => Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
        h => o.PreviewMouseLeftButtonDown += h,
        h => o.PreviewMouseLeftButtonDown -= h)
        .Select(_ => Observable.Generate(
            1,
            q => true,
            i => i+1,
            i => i,
            i => i==1
                ? TimeSpan.FromMilliseconds(0)
                : i > 10
                    ? TimeSpan.FromMilliseconds(50)
                    : TimeSpan.FromMilliseconds(500/i))
        .TakeUntil(Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
            h => o.PreviewMouseLeftButtonUp += h,
            h => o.PreviewMouseLeftButtonUp -= h)))
            .Switch()
            .Select(_ => o.Payload)));

最终修改了条件,使第一项立即生效。

什洛莫

Observable.Generate是你的朋友(以及上讨论页)。

对于越来越频繁的值,请替换.Select(_ => Observable.Timer(DateTimeOffset.Now, TimeSpan.FromMilliseconds(o.Frequency))为以下内容:

Observable.Generate(
    1, 
    _ => true,
    i => i + 1,
    i => i,
    i => i > 10
        ? TimeSpan.FromMilliseconds(50)
        : TimeSpan.FromMilliseconds(500 / i)
)            

不管您的模式是什么,都将其装入最后一个参数。您可以将其Generate视为具有所有拨号盘的反应式for循环。


编辑

使用上面的代码,from的第一项Generate将被延迟。如果您要立即获取第一项,然后延迟第二项,则可以执行以下操作:

Observable.Generate(
    1, 
    _ => true,
    i => i + 1,
    i => i,
    i => i > 10
        ? TimeSpan.FromMilliseconds(50)
        : TimeSpan.FromMilliseconds(500 / i)
)            
.StartWith(0)

所以原来.Select(_ => Observable.Timer(DateTimeOffset.Now, TimeSpan.FromMilliseconds(o.Frequency)是现在.Select(_ => Observable.Generate(...).StartWith(0))

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章