Throttling / Event Sequence - Reactive Extensions?

I am looking to implement some kind of throttling behavior in one of my viewmodels. This is a Silverlight application, however I do not consider it particularly important.

Consider a class with three properties:

  • property1
  • property2
  • Property3

When updating one of these properties, an update is required.

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

My goals are as follows:

  • If an update is in progress, we should ideally cancel the call to the server and issue a new request
  • If the property is changed, we should leave a small window of time (perhaps 0.1 seconds), where we are waiting for additional changes. Thus, if several properties change rapidly (for example, programmatically), we will not spam the server with requests. OK for this 0.1 second window to reset with every change, but not required.

If that matters, I use the ChannelFactory implementation to invoke the server.

What patterns can I use for this? Could this help me something reactive expansion?

Edit:

Noting that Paul answers correctly. Although ReactiveUI does not currently work against silverlight5, it clearly describes the approach / layout steps to solve the problem of using Rx.

+7
source share
1 answer

Here's how you would do it with 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); 

Update: Here's how to ensure that there is only one run at a time, with the caveat that you may not get the results in order.

 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); 

The behavior that you describe would in fact be perhaps undesirable, because if the properties change, you get a queue of old requests that you want to publish - you can optimize this if you did something like "BufferingSwitch" () "an operator that did not return its results until it was sure that there were no changes - in fact, it would be great to write.

Moral of the story, Async Complicated ™ :)

+6
source

All Articles