Каким будет наиболее эффективный способ перебора коллекции с большим количеством элементов (1000 и более) и обновления свойств элементов в режиме реального времени? На данный момент моя программа рисует изображение для каждого объекта в коллекции на холсте, используя WriteableBitmap
(хотя я не вижу никакой разницы в производительности между этим и простым эллипсом) и перемещает его по экрану. Я пытаюсь сохранить логику как можно более простой на данный момент.
<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; }
}
(В приведенном выше классе Entity атрибут [Magic] реализует INPC для всех моих свойств)
Я пытался использовать System.Timers.Timer
, System.Threading.Timer
и System.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 элементов и сделаю 1000 без изображения, он все равно будет прерывистым.)
Что я могу сделать, чтобы моя программа более эффективно обрабатывала большие коллекции в режиме реального времени? Я предполагаю, что я многое упускаю, так как это первый раз, когда я имею дело с чем-либо такого рода. Мы будем очень признательны за любые советы.