【问题标题】:an inverse Observable.Throttle逆 Observable.Throttle
【发布时间】:2017-11-07 05:57:42
【问题描述】:

我正在寻找一种可观察的扩展方法来执行反向节流。我的意思是让第一个项目通过,然后在适当的时间内忽略后面的项目。

input - due time 2
|*.*.*..*..|
output
|*......*..|

请注意,这是一个与以下问题不同的问题(它们都是相同的)。下面的问题需要一个固定的抑制持续时间,而我需要一个抑制持续时间,每次新项目过早到达时都会增加抑制持续时间。下面列出的解决方案的输出可视化如下:

input - due time 2
|*.*.*..*..|
output
|*...*..*..|

更新

我想出了以下解决方案,但是我对调度程序和并发性的了解不够,无法确保锁定足够好。当Scheduler参数被添加到方法中时,我也不知道如何实现这个方法。

    public static IObservable<T> InverseThrottle<T>(this IObservable<T> source, TimeSpan dueTime)
    {
        IDisposable coolDownSupscription = null;
        object subscriptionLock = new object();

        return source
            .Where(i =>
            {
                lock (subscriptionLock)
                {
                    bool result;
                    if (coolDownSupscription == null)
                    {
                        result = true;
                    }
                    else
                    {
                        coolDownSupscription.Dispose();
                        result = false;
                    }

                    coolDownSupscription = Observable
                            .Interval(dueTime)
                            .Take(1)
                            .Subscribe(_ =>
                            {
                                lock (subscriptionLock)
                                {
                                    coolDownSupscription = null;
                                }
                            });
                    return result;
                }
            });
    }

【问题讨论】:

    标签: system.reactive


    【解决方案1】:

    你可以使用这样的东西...

    source
        .GroupByUntil(
            x => Unit.Default,
            x => x.Throttle(TimeSpan.FromSeconds(100))
        )
        .SelectMany(
            x => x.ToList().Take(1) // yields first item on completion of the observable.
        );
    

    【讨论】:

    • 油门不会“触发”,也许你想要 Observable.Timer?
    • @PaulBetts Throttle 应该在源流暂停100 时立即“触发”第一项。
    • @PaulBetts。布兰登是对的。一旦源流完成去抖动,Throttle 就会触发,这意味着将产生一个额外的项目,直到它再次完成去抖动,等等。
    • 这对我不起作用,第二个参数 (elementSelector) 是 Func 类型。如果源是 IObservable,g 将不是 IObservable,而是 Unit。
    • 我已经在山洞里躲了 3 年,花了我所有的时间来弄清楚如何让它在 .NET 中工作,我想我终于做到了。不,但说真的,我为仍在寻找的人更新了答案。
    【解决方案2】:

    我推荐这个。

    public static class IObservable_FirstThenThrottle
    {
        public static IObservable<TSource> FirstThenThrottle<TSource>(this IObservable<TSource> source, TimeSpan dueTime)
        {
            var first = source.Take(1);
            var second = source.Skip(1).Throttle(dueTime);
            return first.Merge(second);
        }
    }
    

    当第一个项目进入时触发。然后通过dueTime限制剩余序列。

    这是一个大理石图,显示了dueTime = 2 发生的情况。

    source 0-1-2--3--|
    result 0------2--3--|
    

    【讨论】:

    • 它似乎应该工作,但它没有。输出非常不规则。它还对源代码做了一些时髦的事情,当我在开始时添加一个 Do 来打印每个项目时,第一个项目出现两次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-23
    • 1970-01-01
    • 2018-02-20
    相关资源
    最近更新 更多