C# 泛洪填充中队列抛出内存不足异常

C# 泛洪填充中队列抛出内存不足异常,c#,queue,out-of-memory,C#,Queue,Out Of Memory,我正在使用以下代码对2000 x 2000 x 256位图(内存中)进行整体填充: 当q Count=33554432(~33MB)时,队列抛出内存不足错误。显然,我的记忆力比那强多了。我还创建了一个IntPoint结构,因此每个点都是2个INT,而不是2个Double 有没有办法手动为队列分配更多内存 如果这不可能,有人有其他建议吗 仅供参考:我怀疑这是否重要,但我实际上是在内存中的2000 x 2000字节数组上进行洪水填充,而不是实际加载位图、检查颜色和替换 下面是我从上面引用的链接实现的

我正在使用以下代码对2000 x 2000 x 256位图(内存中)进行整体填充:

当q Count=33554432(~33MB)时,队列抛出内存不足错误。显然,我的记忆力比那强多了。我还创建了一个IntPoint结构,因此每个点都是2个INT,而不是2个Double

  • 有没有办法手动为队列分配更多内存
  • 如果这不可能,有人有其他建议吗
  • 仅供参考:我怀疑这是否重要,但我实际上是在内存中的2000 x 2000字节数组上进行洪水填充,而不是实际加载位图、检查颜色和替换

    下面是我从上面引用的链接实现的洪水填充(可能会跳出一个明显的错误):

    public struct IntPoint
    {
    公共整数X,Y;
    公共积分点(积分p1,积分p2)
    {
    X=p1;
    Y=p2;
    }
    }
    public void TerrainFloodFill(点Tpt、字节TargetLevation、字节替换Terrain)
    {
    IntPoint pt=新IntPoint((int)Tpt.X,(int)Tpt.Y);
    队列q=新队列();
    q、 排队(pt);
    而(q.Count>0)
    {
    IntPoint n=q.Dequeue();
    如果(高度图[(int)n.X,(int)n.Y]!=目标高度)
    继续;
    积分点w=n,e=新积分点(n.X+1,n.Y);
    而((w.X>0)和&HeightMap[(int)w.X,(int)w.Y]==目标高度)
    {
    地形图[(内部)w.X,(内部)w.Y]=替换地形;
    如果((w.Y>0)和高度图[(int)w.X,(int)w.Y-1]==目标高度)
    q、 排队(新输入点(w.X,w.Y-1));
    如果((w.Y0)和高度图[(int)e.X,(int)e.Y-1]==目标高度)
    q、 排队(新积分点(e.X,e.Y-1));
    如果((e.Y<地图高度-1)和&HeightMap[(int)e.X,(int)e.Y+1]==目标高度)
    q、 排队(新输入点(e.X,e.Y+1));
    e、 X++;
    }
    }
    }
    

    一如既往,提前感谢您的帮助

    结构是不可变的,对它们的每次修改都会创建一个新对象,就像原语类型一样。我看到一些X++;和X-;对结构的修改。尝试将IntPoint设置为一个类,这样引用就不会不断更新,看看这是否会改善情况。

    结构是不可变的,每次修改都会创建一个新对象,就像基本类型一样。我看到一些X++;和X-;对结构的修改。尝试将IntPoint设置为一个类,这样引用就不会不断更新,看看这是否会改善情况。

    这可能是一个碎片问题,您应该使用内存分析器来了解发生了什么

    作为第一次尝试

      int estimatedSize = ...;
      Queue<IntPoint> q = new Queue<IntPoint>(estimatedSize);
    
    int estimatedSize=。。。;
    队列q=新队列(估计大小);
    
    我认为类似于
    int estimatedSize=MapWidth将是一个良好的开端


    但是你的队伍还是太大了。当
    targetColor==replacementColor
    时,原始算法可能会失败,这是因为
    HeightMap!=TerrainMap
    。您需要在同一地图上操作,以便设置“像素”将确保在检查其邻居时不会重新排队


    因此,首先将整个高度映射复制到TerrainMap。

    这可能是一个碎片问题,您应该使用内存分析器来找出发生了什么

    作为第一次尝试

      int estimatedSize = ...;
      Queue<IntPoint> q = new Queue<IntPoint>(estimatedSize);
    
    int estimatedSize=。。。;
    队列q=新队列(估计大小);
    
    我认为类似于
    int estimatedSize=MapWidth将是一个良好的开端


    但是你的队伍还是太大了。当
    targetColor==replacementColor
    时,原始算法可能会失败,这是因为
    HeightMap!=TerrainMap
    。您需要在同一地图上操作,以便设置“像素”将确保在检查其邻居时不会重新排队


    因此,首先将整个HeightMap复制到TerrainMap。

    结构应该是不可变的,而这一个不正确。我想我的意思是,他通过修改它来创建大量的结构副本。把它改成一个类,它就更进一步了。在以下位置内存不足:count=59517893(~59 MB)。我也不知道为什么队列会变得这么大。这些副本只会以
    EnQueue()
    作为堆结束,而这正是它们必须的时候。所有其他副本都在堆栈上,无所谓。@zetar-只要将其更改为类,将使
    w=n
    现在意味着完全不同的内容。你的算法现在可能会失败。结构应该是不可变的,但这个不是。我想我的意思是,他通过修改它来创建大量的结构副本。把它改成一个类,它就更进一步了。在以下位置内存不足:count=59517893(~59 MB)。我也不知道为什么队列会变得这么大。这些副本只会以
    EnQueue()
    作为堆结束,而这正是它们必须的时候。所有其他副本都在堆栈上,无所谓。@zetar-只要将其更改为类,将使
    w=n
    现在意味着完全不同的内容。您的算法现在可能会失败。首先,感谢您的建议。无论我将估计大小int estimatedSize=MapHeight*MapWidth*sizeof(int)*2设置得有多高,它的运行空间都在60MB左右;它在哪里(什么时候)运行?你应该回到
    struct
    。是的,我现在回到struct。大小以元素为单位,你的