如果Observable的订阅者需要触发OnNext(),该怎么办?

时间:2013-01-30 16:01:44

标签: c# system.reactive

我有一个跟踪状态的Observable,有点像状态机。

我有Observable的订阅者,可以检测事物何时处于特定状态,并且需要将事物推入新状态,有效地调用Observable上的OnNext()!

这违反了Rx原则,即一次只有一个OnNext()在飞行中!有什么好方法吗?就像调度OnNext()直接在当前的传播完成之后发生?

2 个答案:

答案 0 :(得分:2)

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

可以对Observables(其实质上是离散的值流)进行相同的操作,即声明性地表达控制系统。但是,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;
    }

使用上面的代码,这里是速度管理器的一个示例实现,它可以加速到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);

通过以相同的方式使输入依赖于输出,可以实现Statemachines的情况。

答案 1 :(得分:0)

副手,我会说你可能“想做别的事情” - 也就是说,有另一个注入点进入observable,比如包含类等,有一个方法PushState(...)

无论如何,你可以保留“我会通过IObservable支持Subject<T>或者通过指定你的注射路线来保留”我会告诉你接下来是什么“的语义使用Observable.Create

创建

(虽然Subject<T>被许多人看不起,但由于它是“非纯洁的”)