Improving performance of DataBinding, patience is gold

I came across a performance problem lately. I have a WPF Smart Client application connected to a Dynamics CRM back end. At some point in my application I have add a lot of lines in a data table held by an ObservableCollection class. The problem was each time I add a line into the collection a CollectionChanged event was raised and that triggered the update of some other fields, approximately 10 in my case.
So when was doing batch update the screen freezes for way too much time. I found out the problem was the cascading effect of recalculating all the dependent fields every time I add a ne line in the collection, thanks to the new Visual Studio 2010 performance analysis tools.
In this scenario, I’m only interested to get the totals right when I do the last insert, all other intermediate values are useless. I didn’t want to play with the data binding itself. I could have unbound the total calculation and have it rebinded at the end but I didn’t. Instead I chose to delay the calculation with some kind of sliding expiration timer. Such a timer, set with a timeout of 10 ms, would be reset every time a new add would be made, so if I add a bunch of line in batch odds that the delay between two line add be less than 10 ms is good. In fact it is so good that because it’s almost always true the calculation happens only once at the end.
So there is this magic DelayRun class with its DelayController:


To use this class all you need to do is call the DelayController. The DelayController will handle the creation and the reset process of the DelayRun class. It can handle many delay class at once if they have different key value. Each time the controller Add method is called it either create a new instance of a DelayRun Class of reset the running one.
Here is how you can call it:

This call will delay the Recalc method call for 10 ms. In the mean time if your program add other values to recalc you can recall this line and the delay will be reset for another 10 ms and so on.
Tell me if this can be helpful in your own projects.

2 thoughts on “Improving performance of DataBinding, patience is gold

  1. Good evening Eric De C#

    I just wrote a question about the missing call to InvokeEventCompleted()

    I think the problem is in Execute:

    public void Execute(object state) {
      _resetEvent.WaitOne();
      lock (_timer) {
        _timer.Change(
          Timeout.Infinite,
          Timeout.Infinite);
      }

    Original, but probably wrong:
        //_action.Invoke(_target);
    New and probably OK:
        InvokeEventCompleted(null);

        _resetEvent.Set();
    }

    What do you think about this fix?

    Thanks in advance, kind regards,
    Thomas

  2. Good evenin Eric De C#

    Thanks a lot for this great idea and your source code.

    I tried to use it to delay call’s to WPF’s UpdateSource (realted to UpdateSourceTrigger) and I have noticed, that my action was never called. Then, I noticed, that your function
    InvokeEventCompleted()
    is never called, too.

    I hope that you know where InvokeEventCompleted() should be called as I am not sure where to put it…

    Thanks in advance,
    kind regards,
    Thomas

Leave a Reply