使用Rx执行带有取消的延迟操作

时间:2012-04-03 16:11:06

标签: .net system.reactive

任何人都有示例Rx代码,它显示了由于另一个事件取消的延迟事件而如何执行操作?例如,将鼠标悬停在按钮上一段时间后显示工具提示?

操作是“显示工具提示”

持续时间是“特定时间段”

如果鼠标停留在按钮上方,取消事件将“鼠标移出”。

谢谢!

2 个答案:

答案 0 :(得分:2)

首先将问题分解为您拥有的和您想要的内容,将其转换为函数签名,然后查看是否显示了实现。

  

由于另一个事件取消的延迟事件而执行某项操作

所以你有一个触发源,一个延迟时间和一个取消源

您描述的所需行为是:

  • 对于每个源触发器
  • 延迟指定时间
  • 如果在此期间没有取消,则产生原始值

现在我们有了规范,我们可以签名并考虑实现

??? DelayOrCancel<???>(this IObservable<T> source, 
                       TimeSpan delay, 
                       IObservable<TCancel> cancel);

根据取消来源的性质,您可能需要通过Func<T, IObservable<TCancel>>,但听起来这可能适用于您的情况。

规范的前两行建议SelectMany(源中的每个项目都会生成另一个可观察到的可观察对象)。要获得取消,我们只需要等待延迟或直到取消,我们可以使用TakeUntil。由于最终项目将是源项目,因此返回类型将与源项目相同。

IObservable<T> DelayOrCancel<T, TCancel>(this IObservable<T> source, 
                                         TimeSpan delay, 
                                         IObservable<TCancel> cancel)
{
    //argument checking skipped
    return from s in source
           from i in Observable.Timer(delay).TakeUntil(cancel)
           select s;
}

答案 1 :(得分:0)

IObservable<Unit> startStream;
IObservable<Unit> cancelStream;
TimeSpan delay;

var filtered = Observable
  .Merge(start.Select(_=>true), cancel.Select(_=>false)
  .Throttle(delay)
  .Where(b=>b)
  .Do(_=> ...)
  .Subscribe();

如果您的开始和取消事件不可观察,则需要使用Observable.FromEventPattern转换它们。