在我的WPF应用程序中的某个时刻,一旦我删除和/或向Canvas添加项目,UI线程将锁定约0到约500毫秒(取决于数量)。几次性能测试都指向Canvas。儿童删除主要原因,和。添加也是(删除要严重得多)。我同时删除了大约500个项目,同时添加了大约500项。这大约每秒10次会导致问题。
最后,我编写了一个简单的基准测试应用程序,代码如下。
public MainWindow() {
InitializeComponent();
this.Loaded += (object sender, RoutedEventArgs e) => {
List<Image> a = new List<Image>();
Stopwatch s = new Stopwatch();
s.Start();
for (int i = 0; i < 7500; i++) {
Image img = new Image();
Canvas.SetLeft(img, i * 10);
C.Children.Add(img);
if (i % 10 == 1)
a.Add(img);
}
s.Stop();
long add = s.ElapsedMilliseconds;
s.Reset();
s.Start();
foreach (Image img in a) {
C.Children.Remove(img);
}
s.Stop();
MessageBox.Show(String.Format("Add: {0}, Remove: {1}.", add, s.ElapsedMilliseconds));
};
}
这给出了以下结果(围绕这个,每次我运行它):
Add: 174, Remove: 156.
请记住,只有750个项目被删除,而7500个项目被添加。
这个过程有点重,但我不希望UI(主要是ScrollViewer
)在执行此操作时锁定。我面临的另一个问题是,我不能将其"移动"到另一个Thread
,因为我不能从特定的Thread
控制UI。
如何改进这一过程?或者有没有一种方法可以"随时间"动态添加/删除项目,这样它就不会挂断?
谢谢,
~ Tgys
如果您将其拆分为新线程,并每隔20ms左右将工作调度到UI线程中,会怎么样?这样你就不会完全锁定用户界面。因此,用户可以同时做其他事情。
我知道的其他事情:有AddRange方法吗?也许你可以一次添加所有项目。这样,理论上只会发生一次布局更新,将时间缩短为零。
删除也是如此。参见Canvas.Children.RemoveRange(a);