Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Rx.NET中处理背压,无OnBackpressureTest_C#_F#_System.reactive_Reactive Programming - Fatal编程技术网

C# 在Rx.NET中处理背压,无OnBackpressureTest

C# 在Rx.NET中处理背压,无OnBackpressureTest,c#,f#,system.reactive,reactive-programming,C#,F#,System.reactive,Reactive Programming,我需要在Rx.NET中实现以下算法: 从流中获取最新项目,如果没有新项目,则等待新项目而不阻塞。只有最新的项目重要,其他项目可以删除 将项目输入到SlowFunction并打印输出 重复步骤1 简单的解决方案是: let PrintLatestData (stream: IObservable<_>) = stream.Select(SlowFunction).Subscribe(printfn "%A") 让我们打印最新数据(流:IObservable)= stream.

我需要在Rx.NET中实现以下算法:

  • 中获取最新项目,如果没有新项目,则等待新项目而不阻塞。只有最新的项目重要,其他项目可以删除
  • 将项目输入到
    SlowFunction
    并打印输出
  • 重复步骤1
  • 简单的解决方案是:

    let PrintLatestData (stream: IObservable<_>) =
        stream.Select(SlowFunction).Subscribe(printfn "%A")
    
    让我们打印最新数据(流:IObservable)=
    stream.Select(SlowFunction.Subscribe)(printfn“%A”)
    
    但是,此解决方案不起作用,因为平均而言,
    stream
    发出项目的速度比
    SlowFunction
    消耗项目的速度快。由于
    Select
    不会删除项目,而是尝试按从最旧到最新的顺序处理每个项目,因此随着程序的运行,发送和打印项目之间的延迟将逐渐增大。只有最新的项目应采取从流,以避免这种无限增长的背压


    我搜索了文档,在RxJava中找到了一个名为
    onBackpressureLatest
    的方法,据我所知,该方法可以实现我上面描述的功能。但是,Rx.NET中不存在该方法。如何在Rx.NET中实现这一点?

    同步/异步建议可能会有所帮助,但是,鉴于慢速函数总是比事件流慢,使其异步可能允许您并行处理(在线程池上进行观察),代价是(最终)线程耗尽或通过上下文切换增加更多延迟。对我来说,这听起来不是一个解决办法

    我建议您看看Dave Sexton编写的开源Rxx“内省”操作符。这些可能会改变您从中获取最新信息的缓冲/节流周期,因为队列由于消耗速度慢而备份。如果慢功能突然变快,它根本不会缓冲任何东西。如果速度变慢,它将缓冲更多。 您必须检查是否有“最新发件人”类型,或者仅修改现有类型以满足您的需要。例如,使用缓冲区,只取缓冲区中的最后一项,或进一步增强,只在内部存储最新项。谷歌“Rxx”,你可以在Github的某个地方找到它


    如果“慢功能”的时间是相当可预测的,那么一个更简单的方法就是简单地将流的节流量超过这个时间。很明显,我不是指标准的rx“油门”,而是指一个可以通过更新而不是旧的。这里有很多解决这类问题的方法

    我想您应该使用类似于
    ObserveLatestOn
    的东西。它用一个值和一个标志有效地替换了传入事件的队列

    詹姆斯·沃德在这里写了一篇博客

    这个概念在GUI应用程序中被大量使用,这些应用程序无法相信服务器推送数据的速度

    您还可以在reactivetrader中看到一个实现 以及解释ReactiveTrader的支持演示文稿


    需要说明的是,这是一种减载算法,而不是背压算法。

    不久前,我也遇到了同样的问题,我没有找到一个内置的操作程序能够做到这一点。所以我写了我自己的,我称之为
    Latest
    。实现起来并不简单,但我发现它在我当前的项目中非常有用

    它的工作原理是这样的:当观察者忙于处理之前的通知时(当然是在它自己的线程上),它会将最后的n个通知(n>=0)排队,并在观察者空闲时将其下一个
    s。因此:

    • 最新(0)
      :仅在观察者空闲时观察到达的项目
    • 最新版本(1)
      :始终遵守最新版本
    • Latest(1000)
      (例如):通常处理所有项目,但如果某个项目被卡在了行中,与其得到一个
      OutOfMemoryException,不如错过一些项目
    • Latest(int.MaxValue)
      :决不要错过任何项目,但要在生产者和消费者之间保持负载平衡
    因此,您的代码将是:
    stream.Latest(1)、Select(SlowFunction)、Subscribe(printfn“%A”)

    签名如下所示:

    /// <summary>
    /// Avoids backpressure by enqueuing items when the <paramref name="source"/> produces them more rapidly than the observer can process.
    /// </summary>
    /// <param name="source">The source sequence.</param>
    /// <param name="maxQueueSize">Maximum queue size. If the queue gets full, less recent items are discarded from the queue.</param>
    /// <param name="scheduler">Optional, default: <see cref="Scheduler.Default"/>: <see cref="IScheduler"/> on which to observe notifications.</param>
    /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
    /// <exception cref="ArgumentOutOfRangeException"><paramref name="maxQueueSize"/> is negative.</exception>
    /// <remarks>
    /// A <paramref name="maxQueueSize"/> of 0 observes items only if the subscriber is ready.
    /// A <paramref name="maxQueueSize"/> of 1 guarantees to observe the last item in the sequence, if any.
    /// To observe the whole source sequence, specify <see cref="int.MaxValue"/>.
    /// </remarks>
    public static IObservable<TSource> Latest<TSource>(this IObservable<TSource> source, int maxQueueSize, IScheduler scheduler = null)
    
    //
    ///当观察者生成项目的速度快于观察者处理项目的速度时,通过将项目排队来避免背压。
    /// 
    ///源序列。
    ///最大队列大小。如果队列已满,则较新的项目将从队列中丢弃。
    ///可选,默认::要在其上观察通知。
    ///是空的。
    ///答案是否定的。
    /// 
    ///只有在订阅者准备就绪时,0才能观察项目。
    ///如果有,1保证观察序列中的最后一项。
    ///要观察整个源序列,请指定。
    /// 
    公共静态IObservable Latest(此IObservable源,int maxQueueSize,IsScheduler scheduler=null)
    

    实现太大,无法在这里发布,但如果有人感兴趣,我很乐意与大家分享。让我知道。

    您可以
    以您知道的间隔对流进行采样
    慢功能
    可以处理。下面是一个java示例:

    TestScheduler ts=newtestscheduler();
    可观测流=可观测的间隔(1,TimeUnit.ms,ts).take(500);
    stream.sample(100,TimeUnit.ms,ts).subscribe(System.out::println);
    ts.advanceTimeBy(1000,时间单位毫秒);
    
    98
    198
    298
    398
    498
    499
    
    示例
    不会产生背压,并且始终获取流中的最新值,因此它满足您的要求。另外,
    sample
    不会两次发送相同的值(从上面可以看出,
    499
    只打印一次)

    我认为这将是一个有效的
    C
    /
    F
    解决方案:

    static IDisposable PrintLatestData<T>(IObservable<T> stream) {
        return stream.Sample(TimeSpan.FromMilliseconds(100))
            .Select(SlowFunction)
            .Subscribe(Console.WriteLine);
    }
    
    静态IDisposable PrintLatestData(IObservable流){
    返回stream.Sample(TimeSpan.From毫秒(100))
    .选择(慢功能)
    .Subscribe(Console.WriteLine);
    }
    
    让我们打印最新数据(流:IObservable)=
    str
    
    let PrintLatestData (stream: IObservable<_>) =
        stream.Sample(TimeSpan.FromMilliseconds(100))
            .Select(SlowFunction)
            .Subscribe(printfn "%A")