如何访问系统内部的WPF控件



首先,我必须猜测我对异步没有太多经验。

我正在使用VS2015在WPF应用程序上合作,其中我有一个蒙版设计师。在那里,我可以通过拖放,移动和调整大小,将控件添加到画布中。大小和位置的更改暂时存储在字典中,并通过单击"保存按钮"来保存到数据库中。

为了优化更新的速度,我认为通过异步系统替换同步的foreach是一件好事。但是现在我有一个问题,我无法使用某些WPF控件(例如控件都在躺在的画布),因为它们属于主线程。

如何在循环内访问这些控件?

这是我代码的实验,这使我在此时间问题上有问题:

Parallel.ForEach(ChangedElements, (changedElement) =>
{
    FrameworkElement element = elementHelper.GetElementFromPanel(changedElement.Value, designerwindow.maskDesignerPanel);
    elementHelper.UpdateElementPositionAndSize(element, designerwindow, inputFieldList);
});

"更改元素"是带有更改WPF元素的名称的字典。最初是类型,但我将其更改为,因此键和值包含控件的名称/标识符。" DesignerWindow"是对WPF窗口和" MaskDesignerPanel"的引用。在运行时,当我尝试从画布的儿童收藏中获取元素时,方法GetElementFrompanel中的错误。在这种情况下,我无法访问儿童收藏,因为它属于主线程。

在这里,方法GetElementFrompanel的代码:

    public FrameworkElement GetElementFromPanel(string elementName, Canvas panel)
    {
        FrameworkElement element = null;
        foreach (FrameworkElement child in panel.Children)
        {
            if (child.Name == elementName)
            {
                element = child;
                break;
            }
        }
        return element;
    }

upd 如果您有成千上万的元素和高频更新的快速,便宜的方法来加速getElementFrompanel:将所有元素放入字典中<>按唯一的名称键,因此您不必每次都必须扫描所有孩子。

关于多线程

  1. 在进行优化之前,您应该证明您的假设与Profiler,您的代码的哪一部分很重?
  2. 如果您看到UI的更新很慢,则无需进行多线程(所有线程都将等待主UI线程)
  3. 如果您发现算法的某些部分很慢,则优化它(不是UI相互作用,我的意思是算法,算法)
  4. 只是将重型代码推开
  5. 如果算法仍然很慢,请确保算法可以并行,如果您可以采用这种方式之一:

a。调度程序。撤消方法:只需运行一些刷新UI的代码https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v = vs.110).aspx

b。使用生产者消费者模式与阻塞票据之类的东西。将数据推到处理,在某些线程中处理,然后按主线程以显示结果 https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/blockingcollection-collection-collection-overview

c。使用反应性编程https://msdn.microsoft.com/en-us/library/hh242985(v = vs.103).aspx

d。如果您想删除UI冻结,请使用异步/等待或直接运行UI线程的重型代码。

....很多其他方法

也要在进行多线程之前更好地解开和拆分ui-get零件,过程零件和代码的UI-REFRESH。

最新更新