gpt4 book ai didi

c# - 实时更新大量对象(1,000+)的最有效方法

转载 作者:行者123 更新时间:2023-11-30 17:03:12 27 4
gpt4 key购买 nike

遍历包含大量项目(1,000 或更多)的集合并实时更新项目属性的最有效方法是什么?目前,我的程序使用 WriteableBitmap 在 Canvas 上为集合中的每个对象绘制图像(尽管我没有看到一个简单的椭圆在性能上有任何差异)并将它移动到屏幕。我暂时尽量保持逻辑简单。

<UserControl.Resources>
<DataTemplate DataType="{x:Type local:Entity}">
<Canvas>
<Image Canvas.Left="{Binding Location.X}"
Canvas.Top="{Binding Location.Y}"
Width="{Binding Width}"
Height="{Binding Height}"
Source="{Binding Image}" />
</Canvas>
</DataTemplate>
</UserControl.Resources>

<Canvas x:Name="content"
Width="2000"
Height="2000"
Background="LightGreen">
<ItemsControl Canvas.ZIndex="2" ItemsSource="{Binding Entities}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

[Magic]
public class Entity : ObservableObject
{
public Entity()
{
Height = 16;
Width = 16;
Location = new Vector(Global.rand.Next(800), Global.rand.Next(800));
Image = Global.LoadBitmap("Resources/Thing1.png");
}

public int Height { get; set; }
public int Width { get; set; }
public Vector Location { get; set; }
public WriteableBitmap Image { get; set; }
}

(在上面的实体类中,[Magic] 属性在我的所有属性上实现了 INPC)

我已经尝试使用 System.Timers.TimerSystem.Threading.TimerSystem.Threading.DispatcherTimer 来创建循环以不同的间隔。在我收集到大约 800 个对象之前,所有对象都表现得很好,然后它们开始变得不稳定。我也尝试过使用标准的 foreach 循环和 Parallel.ForEach 循环,并没有真正注意到两者之间的区别。我的循环有更复杂的逻辑,但在我弄清楚如何简化流程之前,我已使其尽可能简单:

void Timer_Tick(object sender, EventArgs e)
{
Parallel.ForEach(Entities, entity =>
{
entity.Location = new Vector(entity.Location.X + 1, entity.Location.Y);
});
}

(此外,这不是 Canvas 的问题;如果我绘制 10 个项目并制作 1,000 个而没有图像,它仍然会变得不稳定。)

如何使我的程序更有效地实时处理大型集合?我猜我遗漏了很多东西,因为这是我第一次处理这种性质的事情。任何建议将不胜感激。

最佳答案

集合最好在一个线程中处理,但也有一些选择:

  • 如果任何进程需要一些长时间且不完全消耗 CPU 的操作,您将在问题中使用您的方法,即thread-per-action。。 p>

  • 如果有多个集合且流程操作时间很短,您最好只对所有集合使用一个线程

如果在线程之间进行同步,也会对性能产生影响。如果您经常这样做,可能会降低速度。

在任何情况下,总有一个思考的地方,并且是强制性的——用于对处理您的操作的不同方法进行基准测试。后一个选项将帮助您了解多任务工作流程。


在一些轻量级算术 CPU 绑定(bind)操作的情况下,您可以随意为所有这些操作使用一个线程。


每个集合一个线程

List<List<Action>> actions = InitializeActions();

foreach(var list in actions)
{
var listCopy = list; // Mandatory where execution is deferred.

// Each collection is stared on different thread from thread pool.
Task.Factory.StartNew(() =>
{
foreach(var action in listCopy)
{
action();
}
}
}

每一个线程

// Single thread executes all the code.
List<List<Action>> actions = InitializeActions();

foreach(var list in actions)
{
foreach(var action in listCopy)
{
action();
}
}

每次操作线程数

List<List<Action>> actions = InitializeActions();

foreach(var list in actions)
{
foreach(var action in listCopy)
{
// Spawn a thread on each action.
Task.Factory.StartNew(action);
}
}

这当然非常简单粗暴,但您明白了。

关于c# - 实时更新大量对象(1,000+)的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18858158/

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