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