在儿童控制Meathoverride oka uielement上的性能。

发布于 2025-02-10 12:17:38 字数 2431 浏览 1 评论 0原文

有一个功能可以绘制我试图加速的10k不同尺寸的矩形。 将RECT分组分配,每个组可能包含超过1K的RECT。

在MenevoSoverride()和10s+上绘制大约20s+的所有矩形需要30s+。当基本童年(又称一个组)具有数百万个矩形时,需要花费很多时间来做foreach。

public class MyPanel : Panel
{

    protected override Size MeasureOverride(Size constraint)
    {
        Size availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        foreach (UIElement element in base.InternalChildren)
        {
            if (element != null)
            {
                element.Measure(availableSize);
            }
        }
        return new Size();
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement element in base.InternalChildren)
        {                
            if (!element.IsMeasureValid)
                continue;

            var x = GetX(element);
            var y = GetY(element);

            var width = element.DesiredSize.Width;
            var height = element.DesiredSize.Height;
            element.Arrange(new Rect(x - width * 0.5, y - height * 0.5, width, height));
        }
        return finalSize;
    }
}

这个从面板中派生的类具有很多功能,我不能简单地用矩形或边框替换它。因此,我尝试从中做foreach,这样:

    protected override Size MeasureOverride(Size constraint)
    {
        var list = base.InternalChildren.Cast<UIElement>().ToList();
        Size availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        MeeasureTest(list, constraint);

        return new Size();
    }

    private void MeeasureTest(List<UIElement> list, Size availableSize)
    {
        Stopwatch watch = Stopwatch.StartNew();           

        //Parallel.ForEach(list, element =>
        //{
        //    if (element != null && !element.IsArrangeValid)
        //    {
        //        element.Measure(availableSize);
        //    }
        //});

        foreach (UIElement element in list)
        {
            this.Dispatcher.BeginInvoke((Action)delegate ()
            {
                if (element != null)
                {
                    element.Measure(availableSize);
                }
            });
        }

        watch.Stop();
        Console.WriteLine("Measure " + DateTime.Now.ToLongTimeString() + " - " + watch.ElapsedMilliseconds);
    }

事实证明,如果我使用并行。如果我在foreach内使用dispatcher.begininvoke,它将尽快执行。但是所有的矩形仍然需要30s+才能显示,我想在UI线程中,它仍然需要一个一个一个。

我在尝试错误的方向吗?谁能给一些提示?

There's a function to draw over 10k different size rects that i try to speed up.
Rects are divided in groups, and each group may contains over 1k rects.

It takes 30s+ to draw all the rects, about 20s+ on MeasureOverride() and 10s+ on ArrangeOverride(). It takes a lot time to do the foreach, when the base.InternalChildren (aka a group) has hundreds even thousands of rects.

public class MyPanel : Panel
{

    protected override Size MeasureOverride(Size constraint)
    {
        Size availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        foreach (UIElement element in base.InternalChildren)
        {
            if (element != null)
            {
                element.Measure(availableSize);
            }
        }
        return new Size();
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (UIElement element in base.InternalChildren)
        {                
            if (!element.IsMeasureValid)
                continue;

            var x = GetX(element);
            var y = GetY(element);

            var width = element.DesiredSize.Width;
            var height = element.DesiredSize.Height;
            element.Arrange(new Rect(x - width * 0.5, y - height * 0.5, width, height));
        }
        return finalSize;
    }
}

this derived class from Panel has a lot function on it, I can't simply replace it with a rectangle or border. So I try to do the foreach out of it, like this:

    protected override Size MeasureOverride(Size constraint)
    {
        var list = base.InternalChildren.Cast<UIElement>().ToList();
        Size availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
        MeeasureTest(list, constraint);

        return new Size();
    }

    private void MeeasureTest(List<UIElement> list, Size availableSize)
    {
        Stopwatch watch = Stopwatch.StartNew();           

        //Parallel.ForEach(list, element =>
        //{
        //    if (element != null && !element.IsArrangeValid)
        //    {
        //        element.Measure(availableSize);
        //    }
        //});

        foreach (UIElement element in list)
        {
            this.Dispatcher.BeginInvoke((Action)delegate ()
            {
                if (element != null)
                {
                    element.Measure(availableSize);
                }
            });
        }

        watch.Stop();
        Console.WriteLine("Measure " + DateTime.Now.ToLongTimeString() + " - " + watch.ElapsedMilliseconds);
    }

It turns out, if I use Parallel.Foreach, it'll cause a thread exception. if I use Dispatcher.BeginInvoke inside the foreach, it'll execute soon. BUT all the rects still need 30s+ to be shown, i guess in the UI thread it still need to be measured one by one.

Am I trying the wrong direction? Can anyone give some tips pls?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文