简体   繁体   English

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

[英]How can I fix race condition in this “reset after time” observable?

Input is an observable that produces a value each time a problem occurs. 输入是可观察的,每次出现问题时都会产生一个值。

As output I want an observable that produces a value if problems exist for a longer time. 作为输出,我希望如果问题存在时间较长,则可观察值会产生一个值。 In other words I want to "reset" the output observable (not produce values) if the last problem is outdated. 换句话说,如果最后一个问题已过时,我想“重置”可观察的输出(不产生值)。

My solution: 我的解决方案:

// 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

I think the okStatusObservable might contain a race condition: If input receives events at time interval of exactly longerTime and second merge part ( Select / false ) would produce a boolean before the first part ( Select + Throttle / true ) then this would result in okStatus to be true 99.9% of the time where the opposite would be correct. 我认为okStatusObservable可能包含竞争条件:如果输入以恰好longerTime时间间隔接收事件,并且第二个合并部分( Select / false )会在第一个部分( Select + Throttle / true )之前产生一个布尔值,那么这将导致okStatus是true的时间,其中所述对面将是正确99.9%。

(PS: to have status value from beginning, we might add .StartWith(true) but that doesn't matter regarding race condition.) (PS:要从一开始就具有状态值,我们可以添加.StartWith(true)但这与竞争条件无关紧要。)

A cleaner way to do the first observable is as follows: 进行第一个可观察的更干净的方法如下:

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

Explanation: For each input message, produce an observable that starts with a false, and after longerTime produces a true. 说明:对于每个input消息,产生一个以false开头的observable,然后在longerTime之后产生一个true。 The Switch means that if you have a new observable, just switch to it, which would exclude the all-clear true at the end. Switch表示如果您有一个新的可观察值,只需切换到它,这将在最后排除所有明显的true

For your second observable, unless longerTime differs between the two observables, every first false in the first observable will result in a false in the second. 对于您的第二个可观察longerTime ,除非两个可观察longerTime之间的longerTime有所不同,否则第一个可观察longerTime每个第一个false将导致第二个可观察longerTime中的false Is that your intention? 那是你的意图吗?

Also, your Where is messed up (should be .Where(b => !b) or .Where(b => b == false) . .Where(_ => false) will always evaluate to false returning nothing. 另外,您的Where搞砸了(应该是.Where(b => !b).Where(b => b == false) 。. .Where(_ => false)将始终为false,不返回任何内容。

Other than that, I think your solution is sound. 除此之外,我认为您的解决方案是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM