多数のアイテム (1,000 以上) を持つコレクションを反復処理し、アイテムのプロパティをリアルタイムで更新する最も効率的な方法は何でしょうか? 現時点では、私のプログラムはキャンバス上のコレクション内の各オブジェクトの画像を描画し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
ましたが、2 つの違いに実際には気づいていません。私のループにはもっと複雑なロジックがありましたが、プロセスを合理化する方法がわかるまで、できるだけシンプルにしました。
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 個のアイテムを画像なしで作成すると、それでも途切れ途切れになります。)
プログラムで大規模なコレクションをより効率的にリアルタイムで処理するにはどうすればよいですか? このような性質のものを扱ったのはこれが初めてなので、見逃している部分がかなりあると思います。アドバイスをいただければ幸いです。