OnPropertyChanged strange performance problem

OnPropertyChanged strange performance problem

Old forum URL: forums.lhotka.net/forums/t/9624.aspx


Michael posted on Monday, October 11, 2010

I have a "Parent" BB object with a "Children" BLB of "Child". Each Child has an "InnerChild" BB. The Child exposes some of the InnerChild properties as pass-throughs, e.g.

public double Something
{
    get { return InnerChild.Something; }
}

InnerChild notifies Child when these properties change, and then Child raises OnPropertyChanged(propertyName);

This forces a grid bound to the Children collection to refresh immediately when the InnerChild is changed in a master-detail edit dialog. This works fine.

However, the Parent has a property which modifies the properties of InnerChild. There is no binding source for Children/Child/InnerChild at this point. Each time the InnerChild property is modified, the OnPropertyChanged call takes about 25ms longer. So, simply typing 1, 0, 0, 0, 0 in the Parent field results in the OnPropertyChanged call taking 69, 95, 121, 148, 173ms respectively. This only happens when the Children are not in binding edit.

If I raise OnPropertyChanged only when Child's BindingEdit == true, is this safe? (BindingEdit says FOR INTERNAL CSLA .NET USE ONLY!)

Is there another fix or workaround?

Thanks in advance.
Michael

Michael replied on Monday, October 11, 2010

Hmmm, it's not the whole story. Conditionally raising OnPropertyChanged does hides the performance problem in the Parent edit screen; it actually still exists in the Children edit dialog. If I've made changes in the Parent fields that alter the InnerChild objects, the same performance degradation is displayed when the Children dialog is used. Commenting out the OnPropertyChanged calls makes everything run fast again.

Michael replied on Monday, October 11, 2010

A friend mentioned a bug with CSLA's LINQ implementation where it hangs onto objects and stops them being garbage collected, and amazingly, that is the problem here. I never would have found this on my own. Changing the following function reduced the OnPropertyChanged calls to 1ms consistently.

        public CushionHeadSpigot GetCushionHeadSpigot(Guid openingId)
        {
            foreach (var item in this)
                if (item.OpeningId == openingId)
                    return item;

            return null;

            //return this.Where(s => s.OpeningId == openingId).FirstOrDefault();
        }

I can't see this in the change logs, or known bugs. Rocky?

RockfordLhotka replied on Monday, October 11, 2010

CSLA 4 addresses this problem by entirely discarding the 3.x LINQ implementation in favor of an explicit step to get a LinqObservableCollection. So I rather suspect this is fixed, because CSLA no longer does any custom LINQ processing.

Michael replied on Monday, October 11, 2010

Excellent, thanks.

Copyright (c) Marimer LLC