我有一个跟踪状态的Observable,有点像状态机。
我有Observable的订阅者,可以检测事物何时处于特定状态,并且需要将事物推入新状态,有效地调用Observable上的OnNext()!
这违反了Rx原则,即一次只有一个OnNext()在飞行中!有什么好方法吗?就像调度OnNext()直接在当前的传播完成之后发生?
答案 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>
被许多人看不起,但由于它是“非纯洁的”)