views:

101

answers:

1

Hi,

I'm wondering if there is a way to convert this so it would be more performant by using a Parallel.For for example.

public FrameworkElement FindIntersectingElement(Rect rectangle, UIElement activeElement)
{    
    foreach (var child in this.Children)
    {
        if (child != activeElement)
        {
            if (GetBounds(child as FrameworkElement, this).IntersectsWith(rectangle))
            {
                return child as FrameworkElement;
            }
        }
    }

    return null;
}

public Rect GetBounds(FrameworkElement of, FrameworkElement from)
{
    GeneralTransform transform = null;

    transform = of.TransformToVisual(from);

    return transform.TransformBounds(new Rect(0, 0, of.ActualWidth, of.ActualHeight));
}

Any suggestions?

+1  A: 

I didn't actually test the following, so use at your own risk (-:
I'm assuming that reading ActualWidth/Height is thread-safe.

   public FrameworkElement FindIntersectingElement(Rect rectangle, UIElement activeElement)
    {
        FrameworkElement found = null;

        System.Threading.Tasks.Parallel.ForEach((IEnumerable<UIElement>)MainPanel.Children, 
           (child, loopState) =>
        {
            if (child != activeElement)
            {
                if (GetBounds(child as FrameworkElement, MainPanel).IntersectsWith(rectangle))
                {
                    found = child as FrameworkElement;
                    loopState.Stop();
                }
            }
        });
        return found;
    }

And to answer the Title-question: You may see some speedup and with many nested elements it might be worth-while. This (tree-searching) is a rare case where you may see a better-than-linear improvement.

Henk Holterman
Thank you, works very well. And with a large number of elements I do indeed see a speedup (testing on an 8 core machine). Restricting the affinity to a single core shows the difference as well
TimothyP
I do no think the cast (IEnumerable<UIElement>) will work, since UIElementCollection is not a generic type?
Chris Taylor
@Chris, Timothy already reported that it is working.
Henk Holterman
@Henk, thanks I was typing the message when that came in so... But I am still perplexed, and this is not to be argumentative I really want to know what the correct syntax is. Using the code above I get an InvalidCastException '"Unable to cast object of type 'System.Windows.Controls.UIElementCollection' to type 'System.Collections.Generic.IEnumerable`1[System.Windows.UIElement]'.".
Chris Taylor
I first simply used MainPanel.Children, but the compile (C#4) complained about "not able to infer type". The typecast does work for me. Are you using VS2008? Note that I substituted a DockPanel for 'this', as a mock-up.
Henk Holterman
I am using C# 4, and the root element is a Grid. I added a DockPanel to the grid and use the DockPanel as the root element, but I get the same problem. Ah well I will keep looking maybe I spot what I am missing. Thanks!
Chris Taylor
Hi, I'll post the exact version I used based on Henk's suggestion.Before I was able to edit posts... but with the recalculation of the stats... I'll have to add it instead
TimothyP