更快地在迭代期间锁定List <t>或克隆</t>

时间:2012-10-17 07:37:06

标签: c# locking gdi+

我目前有一个程序拦截一些数据包,根据信息对列表进行一些修改/添加类并发送它。

我目前正在做的是当我添加一个项目时,我在添加它时锁定了我添加的列表。但是我有一个PictureBox,它每50ms左右从列表中提取信息。目前我的方式看起来像这样:

Graphics g = e.Graphics;

lock (Core.Collections.SpaceStations)
{
    foreach (Classes.Station station in Core.Collections.SpaceStations)
    {
        Image img;
        switch (station.Company)
        {
            case 1:
                img = Prog.Properties.Resources.mmo_station;
                break;
            case 2:
                img = Prog.Properties.Resources.eic_station;
                break;
            case 3:
                img = Prog.Properties.Resources.vru_station;
                break;
            default:
                img = new Bitmap(50, 50);
                break;
        }
        g.DrawImage(img, (float)((station.Position.x - 750) / Core.CurrentMap.ByX), (float)((station.Position.y - 750) / Core.CurrentMap.ByY), 35, 35);
    }
}

正如您所看到的,它会锁定迭代的整个长度,导致我的数据包处理程序阻塞,直到它完成绘制,并且可能导致服务器和客户端的延迟(因为我在添加或删除数据包中的项之前锁定处理程序)。我的问题是,将列表中的所有项目复制到锁定内的临时列表中,然后从临时列表中将它们全部绘制到锁定之外会更快吗?主要是我的问题是,迭代列表或复制列表是否更快。

2 个答案:

答案 0 :(得分:1)

您可以实现自己的列表,允许您在通过列表进行迭代(只读)时添加项目。只有在删除项目时才需要锁定列表以防止迭代。

当然,迭代线程在迭代时不知道新项目。

优点:

  • 在列表容量不变的情况下避免复制,如果更改,则读取器仍然可以完成读取。如果更改,您仍需要在将列表项复制到新阵列时锁定列表。
  • 允许多个线程迭代
  • 允许在迭代时将项目添加到列表中

免责声明:这是非常概念性的,从不测试

答案 1 :(得分:0)

我认为复制列表是更好的选择。

它将极大地提高性能,但会占用大量内存,可以通过在绘制后正确处理列表来进行处理。

Station[] stations = Core.Collections.SpaceStations.ToArray();