我希望在我的一个视图模型中实现一些限制行为.这是一个Silverlight应用程序,但我认为这不是特别重要.
考虑一个具有三个属性的类:
> Property1
> Property2
> Property3
每当更新其中一个属性时,都需要刷新.
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,RxApp.DeferredScheduler) .Select(_ => Observable.Defer(() => FetchNewData())) .Merge(1) .ToProperty(this,x => x.Data);
您描述的行为实际上可能不太可取,因为如果属性不断变化,您最终将会发出旧请求的队列 – 如果您创建类似“BufferingSwitch()”运算符的内容,则可以对此进行优化在确定没有变化之前没有返回结果 – 这实际上很酷.
故事的道德,Async Is Complicated™:)