在WPF中快速删除(并添加)许多项目到Canvas

时间:2012-09-20 13:44:08

标签: c# wpf performance wpf-controls uielementcollection

在我的WPF应用程序中的某一点,一旦我删除和/或添加项目到Canvas,UI线程将锁定〜0到~500 ms(取决于数量)。几个性能测试指出Canvas.Children.Remove是主要原因,而.Add也是(.Remove更严重)。 我同时删除了大约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控制用户界面。

如何改善这个过程?或者有没有办法动态添加/删除项目“随着时间的推移”,所以它不挂断?

谢谢,

〜Tgys

1 个答案:

答案 0 :(得分:2)

如果将其拆分为新线程并将工作分配到UI线程每20分钟左右怎么办?这样你就不会完全锁定UI了。因此,用户可以同时做其他事情。

我知道的其他事情: 有AddRange方法吗?也许你可以一次添加所有项目。这样,理论上只会发生一次布局更新,将时间缩短为零。

删除相同。见Canvas.Children.RemoveRange(a);