首先,我必须猜测我对异步没有太多经验。
我正在使用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:将所有元素放入字典中<>按唯一的名称键,因此您不必每次都必须扫描所有孩子。
关于多线程
- 在进行优化之前,您应该证明您的假设与Profiler,您的代码的哪一部分很重?
- 如果您看到UI的更新很慢,则无需进行多线程(所有线程都将等待主UI线程) )
- 如果您发现算法的某些部分很慢,则优化它(不是UI相互作用,我的意思是算法,算法)
- 只是将重型代码推开
- 如果算法仍然很慢,请确保算法可以并行,如果您可以采用这种方式之一:
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。