<T> 在迭代期间锁定列表或克隆速度更快



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

我目前正在做的是当我添加一个项目时,我会在添加它时锁定要添加到的列表。但是,我有一个图片框,它每 50 毫秒左右从列表中提取一次信息。目前我的做法看起来像这样:

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

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

你可以实现你自己的列表,它允许你在迭代(只读)列表时添加项目。仅当您删除项目时,才需要锁定列表以防止循环访问它。

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

好处:

  • 避免在列表容量不变时复制,如果列表容量发生变化,读者仍然可以完成阅读。如果它发生变化,您仍然需要在将列表项复制到新数组时锁定列表。
  • 允许多个线程循环访问
  • 允许在迭代时向列表添加项

免责声明:这是非常概念化的,永远不要测试它

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

它将明显提高性能,但会占用大量内存,可以通过在绘制后正确处理列表来扩展内存。

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

最新更新