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

private void ShowFor(TimeSpan? delay)
{
   Visible = true;

   if (!delay.HasValue) return;

  // _pauseTimer is a MultipleAssignmentDisposable
  _pauseTimer.Disposable = Observable
     .Timer(delay.Value)
     .ObserveOn(SynchronizationContext.Current)
     .Subscribe(
          onNext:  _ => { /* do nothing */ },
     onCompleted: () => { Visible = false; },
         onError:  e => { /* what could possibly go wrong? */});
}


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

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

如何“中止”先前的计时器?处置pauseTimer.Disposable

最佳答案

您可以将显示控件与隐藏控件分开。假设消息来自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可用于确定需要从当前列表中删除的消息。

关于c# - react 性扩展-中止/取消OnCompleted,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32123468/

10-12 16:22