gpt4 book ai didi

c# - 向 Canvas 添加许多 UIElement 时如何保持 UI 响应?

转载 作者:行者123 更新时间:2023-11-30 16:58:44 34 4
gpt4 key购买 nike

我有多达 70000 个形状派生对象要添加到 Canvas 中。显然,这会导致 UI 无响应,在我的情况下会持续大约 20 秒。我已经尝试使用 Dispatcher 方法来尝试克服这个问题,但我仍然遇到问题。

我的第一种实现方式是这样的:

foreach (var shape in ShapeList)
{
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
drawingCanvas.Children.Add(shape);
}));
}

这确实使 UI 响应迅速,但不利的一面是,它需要很长时间(比如 10 分钟?)才能完全添加所有形状。它还会立即显示添加的形状。

我实现它的第二种方式是:

Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
foreach (var shape in ShapeList)
{
drawingCanvas.Children.Add(shape);
}
}));

好吧,这似乎与根本不使用调度程序具有相同的效果。

我已经在单独的线程上尝试了这两种实现,与主线程没有区别。此外,我必须将它们全部添加为单独的 Shape 对象,因为它们中的每一个都必须支持单独的 MouseClickEvents,因此我没有使用 drawingVisual。

那么有什么方法可以保持主窗口的响应速度,同时仍然保持相对快速的添加过程?

谢谢。

*编辑我知道 CanvasVirtualization,但目前我理解它似乎有点复杂。还有其他方法可以使用吗?

最佳答案

您提到的与使用 Dispatcher 相关的两个问题很容易解决或缓解。

  1. 急剧减速(20 秒 -> 10 分钟),以及
  2. 逐渐添加形状

对于 1),您可以通过分批添加项目而不是一次添加一个项目来加快流程,同时仍保持响应能力。对于 2),一个简单的解决方案是隐藏 Canvas ,并在绘制完成后显示它。

所以像这样:

// group shapes into batches
const int batchSize = 100;
var batches = ShapeList.Select((item, index) => new { index = index, item = item })
.GroupBy(item => item.index / batchSize)
.ToArray();

// function to create a local closure for each batch
Action<int> addBatch = batchNumber => {
var batch = batches[batchNumber];
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
foreach (var shape in batch)
{
drawingCanvas.Children.Add(shape.item);
};
if (batchNumber >= batches.Length - 1)
drawingCanvas.Visibility = Visibility.Visible;
}));
};

drawingCanvas.Visibility = Visibility.Collapsed;
for (int i=0 ; i < batches.Length ; i++)
{
addBatch(i);
}

关于c# - 向 Canvas 添加许多 UIElement 时如何保持 UI 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24914656/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com