C# 如果Observable的订户需要触发OnNext(),该怎么办?

C# 如果Observable的订户需要触发OnNext(),该怎么办?,c#,system.reactive,C#,System.reactive,我有一个可以观察到的东西在跟踪一个状态,有点像一个状态机 我有一个Observable的订户,它可以检测事物何时处于特定状态,它需要将事物推入一个新状态,有效地调用Observable上的OnNext() 这违反了Rx原则,即一次只有一个OnNext()在运行中!有什么好办法吗?就像将OnNext()安排在当前一个完成传播后直接发生一样?我会立即说,您可能“想做其他事情”-也就是说,在可观察对象中有另一个注入点,如包含类等。它有一个方法PushState(…) 无论如何,您可以通过使用主题支持I

我有一个可以观察到的东西在跟踪一个状态,有点像一个状态机

我有一个Observable的订户,它可以检测事物何时处于特定状态,它需要将事物推入一个新状态,有效地调用Observable上的OnNext()


这违反了Rx原则,即一次只有一个OnNext()在运行中!有什么好办法吗?就像将OnNext()安排在当前一个完成传播后直接发生一样?

我会立即说,您可能“想做其他事情”-也就是说,在可观察对象中有另一个注入点,如包含类等。它有一个方法
PushState(…)

无论如何,您可以通过使用
主题支持
IObservable
或在创建过程中使用
Observable指定注射路线来保留“我告诉您下一步是什么”语义。创建


(虽然主题被许多人看不起,因为它的“非纯洁性”)

在控制系统理论中,这种类型的系统是一个有反馈的控制回路。它抵制传统的分析,因为系统的输入取决于输出——输出可能是一个连续函数

对可观测数据(本质上是一个离散的值流)也可以这样做,即,以声明方式表示控制系统。不过,C#语义使得实现不是很优雅。(F#有递归绑定选项)

首先,我们需要定义一个用于编写反馈循环的闭包

    public delegate IObservable<T> Feedback<T>(IObservable<T> feedback, out IObservable<T> output);
    public static IObservable<T> FeedbackSystem<T>(Feedback<T> closure)
    {
        IObservable<T> source = Observable.Empty<T>(), output;
        source = closure(Observable.Defer(() => source), out output);
        return output;
    }
public delegate IObservable Feedback(IObservable Feedback,out IObservable output);
公共静态IObservable反馈系统(反馈关闭)
{
IObservable source=Observable.Empty(),输出;
源=关闭(可观察的延迟(()=>源),输出);
返回输出;
}
使用上述方法,这里是一个速度调节器的示例实现,该速度调节器可加速到100,并将速度保持在100以下,即使速度中引入了随机误差

    var system =
    FeedbackSystem((IObservable<double> acceleration, out IObservable<double> velocity) =>
    {
        //Time axis: moves forward every 0.1s
        double t = 0.1; var timeaxis = Observable.Interval(TimeSpan.FromSeconds(t));

        velocity = acceleration.Sample(timeaxis)                //move in time
                               .Scan((u, a) => u + a * t)   //u' = u + at
                               .Select(u => u + new Random().Next(10))  //some variations in speed
                               .Publish().RefCount();                   //avoid recalculation

        //negative feedback
        var feedback = velocity.Select(u => 0.5 * (100 - u));

        return feedback.Select(a => Math.Min(a, 15.0))  //new limited acceleration
                       .StartWith(0);                   //initial value          
    });

    system.Subscribe(Console.WriteLine);
var系统=
反馈系统((可观测加速度,输出可观测速度)=>
{
//时间轴:每0.1s向前移动一次
double t=0.1;var timeaxis=Observable.Interval(TimeSpan.FromSeconds(t));
速度=加速度。采样(时间轴)//随时间移动
.Scan((u,a)=>u+a*t)//u'=u+at
.选择(u=>u+new Random()。下一步(10))//速度的一些变化
.Publish().RefCount();//避免重新计算
//非正面反馈
var反馈=速度。选择(u=>0.5*(100-u));
返回反馈。选择(a=>Math.Min(a,15.0))//新的限制加速度
.StartWith(0);//初始值
});
system.Subscribe(Console.WriteLine);
通过使输入以同样的方式依赖于输出,状态机的情况是可能的