实时更新大量对象(1,000多个)的最有效方法 [英] Most efficient method to update large number of objects (1,000+) in real-time

查看:110
本文介绍了实时更新大量对象(1,000多个)的最有效方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最有效的方法是遍历具有大量项目(1,000个或更多)的集合并实时更新项目的属性?目前,我的程序使用WriteableBitmap在画布上为集合中的每个对象绘制图像(尽管我看不到一个简单的椭圆之间的性能差异)并将其在屏幕上移动.我试图暂时保持逻辑尽可能简单.

What would be the most efficient way to iterate through a collection with a large number of items (1,000 or more) and update the items' properties in real-time? At the moment, my program draws an image for each object in the collection on a canvas using WriteableBitmap (though I don't see any difference in performance between that an a simple ellipse) and moves it across the screen. I am trying to keep the logic as simple as possible for the time being.

<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)

(In the Entity class above, the [Magic] attribute implements INPC on all of my properties)

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

I have tried using System.Timers.Timer, System.Threading.Timer, and System.Threading.DispatcherTimer to create a loop with varying intervals. All behave fairly well until I get to about 800 objects in the collection and then they start to become choppy. I have also tried using a standard foreach loop and a Parallel.ForEach loop and haven't really noticed a difference between the two. My loop had more complex logic, but I have made it as simple as possible until I can figure out how to streamline the process:

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

(此外,画布"也不是问题;如果我绘制10个项目并制作1,000个没有图像的项目,它仍然会变得断断续续.)

(Also, this isn't an issue with the Canvas; if I draw 10 items and make 1,000 with no image it still gets choppy.)

如何使我的程序更有效地实时处理大型馆藏?我猜我很想念我,因为这是我第一次处理这种性质的东西.任何建议将不胜感激.

What can I do to make my program handle large collections in real-time more efficiently? I'm guessing there's a good bit I'm missing as this is the first time I've ever dealt with anything of this nature. Any advice would be greatly appreciated.

推荐答案

最好使用每个线程一个处理集合,但是有一些选择:

Collections are best processed in one-per-thread, but there are some options:

  • 如果任何进程需要一些长时间且不完全消耗CPU的操作,则应在问题中使用您的方法,即每次操作线程.

如果有很多集合具有较少的流程操作时间,则最好只对所有线程使用一个线程.

In case there are number of collections with small process action time, you might be the best to use only one thread for all of them.

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

There is also an influence on performance if you do synchronization between your threads. If you do, and pretty often, that might slow the speed down.

在任何情况下,总有一个思考和强制性的地方-用于基准化处理您的操作的不同方法.后一个选项将帮助您了解多任务工作流程.

In any case, there is always a place to think, and mandatory - for benchmark different methods of processing your action. That latter option will help you understand the multitasked workflow.

对于某些受CPU限制的轻量算法运算,您可以随时使用 a 线程.

In the case of some lightweight arythmetic CPU-bound operations, you are to feel free to use a thread for all of them.

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);
    }
}

这当然非常简单明了,但是您明白了.

This is of course pretty straightforward and rough, but you get the point.

这篇关于实时更新大量对象(1,000多个)的最有效方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆