如何在这种“时间重置”后解决比赛条件?

时间:2019-03-25 12:46:44

标签: c# observable system.reactive race-condition throttling

输入是可观察的,每次出现问题时都会产生一个值。

作为输出,我希望如果问题存在时间较长,则可观察值会产生一个值。换句话说,如果最后一个问题已过时,我想“重置”可观察的输出(不产生值)。

我的解决方案:

// 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的概率为true 99.9%的时间是正确的,而相反的情况是正确的。

(PS:要从一开始就具有状态值,我们可以添加.StartWith(true),但这与种族状况无关紧要。)

1 个答案:

答案 0 :(得分:2)

第一个可观察到的更干净的方法如下:

var okStatusObservable2 = input
    .Select(_ => Observable.Return(true).Delay(longerTime).StartWith(false))
    .Switch();

说明:对于每条input消息,产生一个以false开头的observable,然后在longerTime之后产生一个true。 Switch意味着如果您有一个新的可观察对象,只需切换到它即可,这将最终排除所有清晰的true

对于您的第二个可观察物,除非两个可观察物之间的longerTime不同,否则第一个可观察物的每个第一个false都会在第二个可观察物中产生false。那是你的意图吗?

此外,您的Where被搞砸了(应该是.Where(b => !b).Where(b => b == false).Where(_ => false)始终会返回false,不返回任何内容。

除此之外,我认为您的解决方案是正确的。