不确定我的问题的标题,但希望我可以解释我想要做的事情。
我希望有一个Timer将一个值注入一个序列,但是当观察到一个特定值时。 我希望在序列中输入任何其他值时取消Timer。
public enum State
{
Connected,
Disconnected,
DisconnectedRetryTimeout
}
var stateSubject = new Subject<State>();
var connectionStream = stateSubject.AsObservable();
var disconnectTimer =
Observable.Return(State.DisconnectedRetryTimeout)
.Delay(TimeSpan.FromSeconds(30))
.Concat(Observable.Never<State>());
var disconnectSignal =
disconnectedTimer
.TakeUntil(connectionStream.Where(s => s == State.Connected))
.Repeat();
var statusObservable =
Observable.Merge(connectionStream, disconnectSignal)
.DistinctUntilChanged();
所以当流中没有任何东西(即新的)没有计时器时。 当Connected | DisconnectedRetryTimeout添加无计时器时。 当Disconnected为add时,我希望计时器启动 如果在定时器触发之前已在流上连接,我希望取消定时器 定时器只应触发一次,直到再次收到断开连接。
对RX来说很新,但对这个想法用完了。
任何帮助非常感谢。
答案 0 :(得分:3)
如果我正确理解了问题:我们从一个会发出Connected
或Disconnected
条消息的状态流开始。如果DisconnectedRetryTimeout
消息在流上停留30秒而没有显示Disconnected
消息,则我们希望使用Connected
消息来丰富此消息。
实现此目的的一种方法有以下想法:
将Connected / Disconnected流投影到DisconnectedRetryTimeout流中,如下所示:
DistinctUntilChanged
剥离重复项,因为我们只希望批处理的第一条Disconnected
消息启动计时器。DisconnectedRetryTimeout
的信息流Observable.Never
)Switch
通过始终获取最新的流来平展它。因此,如果在计时器处于运行状态时出现Connect
,则Never
流将替换计时器流。现在我们可以将其与原始的去除流合并。请注意,我们发布了已删除的流,因为我们将订阅它两次 - 如果我们不这样做,并且源是冷的,那么我们可能会遇到问题。详细了解here。
var stateSubject = new Subject<State>();
var state = stateSubject.DistinctUntilChanged().Publish().RefCount();
var disconnectTimer = state
.Select(x => x == State.Disconnected
? Observable.Timer(TimeSpan.FromSeconds(30))
.Select(_ => State.DisconnectedRetryTimeout)
: Observable.Never<State>())
.Switch();
var statusObservable =
state.Merge(disconnectTimer);
您可以一次性执行此操作,然后删除发布步骤并合并 - 使用StartWith
我们可以通过计时器流推送Disconnected
事件,并使用Observable.Return
我们可以通过替换空的Connected
流来推送Never
:
var statusObservable = stateSubject
.DistinctUntilChanged()
.Select(x => x == State.Disconnected
? Observable.Timer(TimeSpan.FromSeconds(5))
.Select(_ => State.DisconnectedRetryTimeout)
.StartWith(State.Disconnected)
: Observable.Return(State.Connected))
.Switch();