输入是一个可观察的,每次出现问题时都会产生一个值。
作为输出,我想要一个observable,如果问题存在较长时间,它会产生一个值。换句话说,如果最后一个问题已经过时,我想“重置”输出可观察(不产生值)。
我的解决方案
// first get an observable producing statusOk values (true = ok, false = not ok)
var okStatusObservable = input.Select(_ => true).Throttle(longerTime)
.Merge(input.Select(_ => false));
// we only want event if statusOk=false for a longer time
var outputObservable = okStatusObservable
.DistinctUntilChanged() // only changes
.Throttle(evenLongerTime) // wait for stable status
.Where(_ => _ == false); // only interested in bad status
我认为okStatusObservable
可能包含竞争条件:如果输入接收事件的时间间隔恰好是longerTime
和第二个合并部分(Select
/ false
)将在第一部分(Select
+ Throttle
/ true
)之前产生一个布尔值,那么这将导致okStatus在相反的情况下,99.9%的时间是true
。
(PS:从开始就有状态值,我们可能会添加.StartWith(true)
,但这与竞争条件无关。)
第一个可观察的清洁方法如下:
var okStatusObservable2 = input
.Select(_ => Observable.Return(true).Delay(longerTime).StartWith(false))
.Switch();
说明:对于每个input
消息,生成一个以false开头的observable,并在longerTime
生成一个true之后。 Switch
意味着如果你有一个新的observable,只需切换到它,这将排除最后的全明确的true
。
对于你的第二个可观测量,除非longerTime
在两个可观测量之间不同,否则第一个可观测量中的每个第一个false
将在第二个观测值中产生false
。这是你的意图吗?
此外,你的Where
搞砸了(应该是.Where(b => !b)
或.Where(b => b == false)
..Where(_ => false)
将总是评估为false,什么都不返回。
除此之外,我认为你的解决方案是合理的。