2012-06-15 20 views
7

我正在寻找实施一些限制行为到我的一个viewmodels。这是一个Silverlight应用程序,但我认为这不是特别重要。事件调节/排队 - 反应性扩展?

考虑具有三个属性的类:

  • Property1
  • Property2
  • Property3

每当这些属性之一被更新,刷新是neccessary。

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

我的目标如下:

  • 如果刷新过程中,我们应该理想地取消呼叫服务器,如果一个属性更改发出一个新的请求
  • ,我们应该留出一小段时间(也许是0.1秒),等待其他更改。这样,如果多个属性快速更改(例如,以编程方式),我们不会将请求发送给服务器。这个0.1秒的窗口可以在每次更改时重置,但不是必需的。

如果问题很重要,我使用ChannelFactory实现进行服务器调用。

我可以用什么样的模式来完成这个?这是反应式扩展可以帮助我吗?

编辑:

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

+1

的Rx绝对支持这一点,看到http://rxwiki.wikidot.com/101samples#toc29 - 关于取消它 - 从任务 –

回答

6

这里是你如何与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); 

您所描述的行为,实际上是也许不是desireable,因为如果性质不断变化,你会老的请求队列最终发行 - 你可以优化这个,如果你做的东西像“BufferingSwitch()”操作符在确定没有变化之前没有返回结果 - 实际上写起来很酷。

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

+0

看一看的CancellationToken谢谢,看起来像我乍一看需要的东西。这对silverlight有效吗?我无法找到WhenAny扩展方法来尝试一下。 –

+0

@ShaunRowan:该扩展名来自ReactiveUI(http://www.reactiveui.net)。以前的版本(v2)支持Silverlight。当前版本(v3)没有。特别是如果你在做MVVM,这是一个非常棒的库。 –

+0

谢谢,我会检查出来的!出于某种原因,我的大脑将“ReactiveUI”与“反应扩展”互换。 (我没有意识到这个库) –