事件限制/排队 - 反应式扩展



我希望在我的一个视图模型中实现一些限制行为。 这是一个银光应用程序,但我认为这不是特别重要。

考虑一个具有三个属性的类:

  • 属性1
  • 属性2
  • 属性3

每当更新这些属性之一时,都需要刷新。

private void Refresh()
{
    //Call out to the server, do something when it comes back
}

我的目标如下:

  • 如果正在进行刷新,理想情况下,我们应该取消对服务器的调用,并发出新的请求
  • 如果属性被更改,我们应该留出一些小的时间窗口(可能是 0.1 秒)来等待其他更改。 这样,如果快速更改多个属性(例如,以编程方式),我们就不会向服务器发送请求垃圾邮件。 每次更改时重置 0.1 秒窗口是可以的,但不是必需的。

如果这很重要,我正在使用ChannelFactory实现进行服务器调用。

我可以使用哪种模式来完成此操作? 这是反应式扩展可以帮助我的事情吗?

编辑:

将保罗的答案标记为正确。 虽然ReactiveUI目前不适用于silverlight5,但它清楚地概述了使用Rx解决问题的方法/组合步骤。

以下是使用 ReactiveUI 执行此操作的方法:

IObservable<TheData> FetchNewData() 
{
    // TODO: Implement me
}
this.WhenAny(x => x.Property1, x => x.Property2, x => x.Property3, (x,y,z) => Unit.Default)
    .Throttle(TimeSpan.FromMilliseconds(200), RxApp.DeferredScheduler)
    .Select(x => FetchNewData())
    .Switch()    // We only care about the req corresp. to latest values of Prop1-3
    .ToProperty(this, x => x.Data);

更新:下面介绍了如何确保一次只有一个正在运行,但需要注意的是,您可能会得到无序结果。

this.WhenAny(x => x.Property1, x => x.Property2, x => x.Property3, (x,y,z) => Unit.Default)
    .Throttle(TimeSpan.FromMilliseconds(200), RxApp.DeferredScheduler)
    .Select(_ => Observable.Defer(() => FetchNewData()))
    .Merge(1)
    .ToProperty(this, x => x.Data);

您描述的行为实际上可能是不可取的,因为如果属性不断更改,您最终会发出一排旧请求 - 如果您制作了类似"BufferingSwitch()"运算符之类的东西,您可以优化它直到确定没有更改时才返回其结果 - 这实际上很酷写。

故事的寓意,异步是复杂的™:)

相关内容

  • 没有找到相关文章

最新更新