Prevent a binding from updating too frequently

During my WPF presentation for the NYC .NET Developer Group a few days ago, someone in the audience asked a question about the data binding system which piqued my interest.  He asked if it is possible to control how frequently a binding target is updated. 

Suppose that you have a data source where a property’s value changes very rapidly, perhaps several dozen times per second.  You would not want the UI to display all of those values because it would just look like a blur.  It would be better to govern how often the binding source’s new values are pushed to the binding target.  The question is, how can you do that in WPF?

One solution is to create a value converter which governs the data flow between source and target.  The converter can keep a time stamp which it uses to determine when the new source values can be pushed to the target.  Every time the data is pushed, the time stamp is updated so that the next push will not occur until a pre-defined duration has elapsed.

I put together a demo app which shows how to do this.  In the demo, the rapidly changing data source is called RandomNumberEngine.  It has a public property named Current, which returns a random number.  That random number changes once every millisecond.  When the value changes, the PropertyChanged event is raised so that the binding system will attempt to push that new value into a TextBlock in the UI.  The TextBlock’s Text property is bound to the Current property on the RandomNumberEngine, and that binding is where we use the UpdateThresholdConverter to govern how often the data is pushed.

Here is the XAML for the demo app’s main Window contents:

Update Threshold Converter (usage)

Here is the entire UpdateThresholdConverter class:

Update Threshold Converter (implementation)

The UpdateThreshold property represents the number of milliseconds which must elapse between successful attempts to push a new value from the binding source to target.  Returning Binding.DoNothing from the Convert method informs the binding system that no values should be updated, leaving the attempt to transfer data as a no-op.

Download the demo project here:  Update Threshold Converter (demo project)  Be sure to change the file extension from .DOC to .ZIP and then decompress it.

Advertisement

9 Responses to Prevent a binding from updating too frequently

  1. Neil Mosafi says:

    Josh

    I’m not too keen on this method and I will explain why. Say you have a source whose value changes very frequently for a number of seconds and then stops changing. You could potentially end up “missing” the last update because it happened within the threshold. Therefore your binding target would not reflect the actual value of the source.

    Also this doesn’t seem like a natural use a converter, which should be to convert between types.

    Have you instead considered using a OneTime binding, and then periodially calling BindingExpression.UpdateTarget() to force an update? This will ensure that the latest values are always propagated from source to target.

    http://msdn2.microsoft.com/en-us/library/system.windows.data.bindingexpression.updatetarget.aspx

    Regards
    Neil

  2. Josh Smith says:

    Neil,

    I agree that this technique is not the ideal way to solve the problem under all circumstances. For the situation you described, where the data source is updated many times and then not updated afterwards, this technique would not be ideal (for the reason you mentioned).

    I disagree that this is not a “natural” use of a value converter. In my opinion a value converter is just an arbitrary piece of code which executes when a bound value moves from source to target, or vice versa. Its primary role is to change the data, but I see no reason why they should be limited to just that. I suppose that is just a stylistic preference.

    Thanks,
    Josh

  3. Travis says:

    Josh,

    I was the one who asked the question at your talk (Which I enjoyed a lot, thanks). Specifically, the scenario I had in mind had to do with financial data. Basically the problem is that I have a bunch of data coming off of a message bus that needs to be displayed to the user, but sometimes it comes in way too fast, not only to view, but sometimes so fast that the redrawing of the UI bogs down the computer. These are usually fast computers too, top of the line. I have built various mechanisms for doing this buffering on the client side, and most of them involve some sort of Dictionary (of say stock symbols and prices for example) that gets dispatched from the messaging code into the program at some defined interval, say 250 or 500ms. This prevents a lot of unnecessary processing from happening, (of which the UI update code is a big part), while maintaining that the message dispatched for any given symbol was the latest to be received.

    Recently though, I came up against a problem where I was computing a lot of stuff on the client side from a number of different message sources, all of them with different dispatch threads and cycles, any of which changing would cause a recalculation and update to the UI. This meant that subject to the arrival of the various different messages, I could still be pushing many updates per second. I was toying around with an idea of “Buffered Events” when I heard you mention the degree of control over data binding that WPF gave you in choosing when to update information from the user and that’s why I asked the question.

    Although I am no WPF expert, In this case I have to agree with Neil in that there is no defined frequency to the message receiving, and in the case where there is a flurry of messages followed by a long period of silence, it is very important that we display whatever the last message was regardless of what the intermediate messages were.

    I do like the elegance of the Converter type though in that it looks really easy to use and customize, and I think I’ll play around with it a little and see if I can come up with something a little more suited to the situation I described. Off the top of my head I envision something where a potential update is buffered for X amount of time the first time it changes, and during that holding period, any newer updates will replace prior updates, with the most recent value being bound after the holding period elapses. The whole process would then reset and wait for more events. The only trouble will be to coordinate the thread(ideally one) or threads that monitor the various holding periods for various symbols.

  4. Josh Smith says:

    Travis,

    Thanks for stopping by. Now that the details of your situation are flushed out more, I agree that the technique shown in this blog post is not appropriate for your situation. You might want to use this idea of a “threshold converter” but also add in the suggestion Neil made of calling UpdateTarget() on the binding expression, perhaps every N milliseconds. A DispatcherTimer could be used to perform the ticking on the correct UI thread.

    Thanks,
    Josh

  5. Patrick says:

    Josh,

    It’s interesting you mention this method – I actually ended up deriving this exact same method myself in something I’m currently working on. In my application, I can be reasonably certain that my data will update regularly, but in the case that it won’t I have a DispatchTimer forcing that particular property to update regularly anyway, at a much longer interval than the data itself. (the only difference is, in my example I call a method I’ve defined myself since what needs to be updated involves regenerating an image, as well).

    It works very well for my purposes so it’s definitely an approach I’d recommend in this sort of scenario.

  6. Dudi says:

    Hi,
    how can i change the UpdateThreshold at runtime via c# and not from the XAML?

    Thanks,
    Dudi

  7. Josh Smith says:

    Dudi,
    Make the converter a resource, get it via FindResource, and then set the UpdateThreshold property.

    Josh

  8. Lynton says:

    Hi Josh and all,

    I used the method of DispatcherTimer in my app as well, but I am having some problems.

    I wrote a sample app to display the time in milliseconds when an updated is triggered by the timer, here is the problems I am having.

    The timer doesn’t tick on the exact interval, say I want my update rate to be 5 Hz, then I would expect the view displays milliseconds as 0, 200, 400, 600, 800, and 0 again, but it doesn’t. The numbers seems a bit “jumpy” sometimes its100, 300, 500, 600, 800, etc.

    Just wondering have you guy seen such problem before and any suggestions on how to fixed?

    Thanks
    Lynton

  9. Josh Smith says:

    Lynton,

    You should not rely on a UI-bound timer, such as DispatcherTimer, to give you a precise interval between ticks. If the UI thread gets bogged down rendering an animation, or someone foolishly decides to download a 100MB file on the UI thread, your timer’s messages won’t be taken off the dispatcher’s queue until the thread is free again.

    Consider using System.Threading.Timer if you can.

    Josh

%d bloggers like this: