Reactive Extensions - 中止/取消OnCompleted

时间:2015-08-20 16:24:00

标签: c# system.reactive reactive-programming

我有一个显示状态消息的控件;控制在间隔后隐藏。以下是处理它的代码:

rbenv local 2.2.2

显示控件,等待 n 秒,隐藏控件。十分简单。

问题是在此计时器过去之前另一条消息进入时该怎么办。第二条消息显示,然后第一个计时器到期并过早隐藏控件。

我怎样才能"中止"以前的计时器?处置gem uninstall bundler

2 个答案:

答案 0 :(得分:2)

_pauseTimer更改为SerialDisposable而不是MultipleAssignmentDisposable,然后每次执行_pauseTimer.Disposable = newDisposable时,它将处理当前订阅,以便订阅下一个。< / p>

答案 1 :(得分:1)

您可以将显示控件与隐藏它分开。假设消息来自IObservable<string> messages(如果它们当前不是很容易设置),那么订阅此消息并使用OnNext中的消息设置控件可见。

另外,订阅相同的流并应用油门以在需要多长时间后隐藏消息,例如:

messages.Throttle(TimeSpan.FromSeconds(1))
        .ObserveOn(SynchronizationContext.Current)
        .Subscribe(_ => control.Visible = false);

只有在没有看到所需延迟的新信息时,油门才会发光。

要考虑不同的延迟,请将消息源设置为包装消息和严重性的类型。为简单起见,我将使用Tuple<string, Timespan>,但您可以使用枚举来表示严重性并执行更精细的操作。油门有一个过载,可以通过任何流来改变它的持续时间。您可以根据消息持续时间创建Throttle源:

// assuming messages is `Tuple<string, Timespan>`
var delayStream = messages.Throttle(
    messages.SelectMany(x => Observable.Timer(x.Item2)))

这将根据消息严重性创建不同的节流,并且您可以使用非常大(最大)的超时来发出严重警告 - 或者只为它们发出Observable.Empty而不是使用计时器。

请注意,根据此方案(以及使用单个控件的描述),新消息会替换先前的消息。一个小的改动会使这很容易处理 - 如果你的控件显示多条消息并且每个消息带有一个id,delayStream可以用来决定哪一个需要从当前列表中删除。