在循环中创建数组会引发OutOfMemoryException

时间:2017-02-13 14:42:56

标签: c#

我正在研究一种用于处理图像的C#软件。我有很多图像(超过11000),当我几分钟后执行我的程序时,我有一个“OutOfMemoryException”

有我的代码:

private void GenerateImages()
{
    try
    {
        Parallel.ForEach(listImagesStart, startImg =>
        {
            bool docontinue = true;
            try
            {
                startImg.LoadImage(_baseFileResults);
            }
            catch
            {
                docontinue = false;
            }
            if (docontinue)
            {
                //Save image as file
                startImg.Save();

                // Do rotate
                MyImg lastRotate = baseImg;
                MyImg imgtmp;
                String[] tabRotate = new String[3] { "_90", "_180", "_270"};
                foreach (String rotate in tabRotate)
                {
                    imgtmp = new GenImg(baseImg.FileName + rotate + baseImg.FileExtension);
                    imgtmp.LoadImage(lastRotate);
                    imgtmp.Rotate90();
                    imgtmp.Save();
                    lastRotate = imgtmp;
                }

                startImg.Dispose();
                imgtmp.Dispose();
            }
        });
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
#if DEBUG
        MessageBox.Show(e.StackTrace, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
#endif
    }
}

和MyImg:

class myImg
{
    public Byte[] Matrix;
    public int Height;
    public int Width;

    public void LoadImage(String filePath)
    {
        // create new Matrix/Heigth/Width from file
    }

    public void LoadImage(myImg img)
    {
        Matrix = new Byte[img.Matrix.Length];
        Array.Copy(img.Matrix, Matrix, img.Matrix.Length);
        Height = img.Height;
        Width = img.Width;
    }

    public void Rotate90()
    {
        // Save before
        int tmpWidth = Height;
        int tmpHeight = Width;
        Byte[] tmpMatrix = new Byte[Matrix.Length];

        for (int r = 0; r < tmpHeight; r++)
        {
            for (int c = 0; c < tmpWidth; c++)
            {
                int prevR = Height - c - 1;
                int prevC = r;
                tmpMatrix[c + r * tmpWidth] = Matrix[prevC + prevR * Width];
            }
        }

        // Copy new image
        Array.Copy(tmpMatrix, Matrix, Matrix.Length);
        Width = tmpWidth;
        Height = tmpHeight;
    }

    public void Dispose()
    {
        SavePath = null;
        Matrix = null;
        Points = null;
        Width = 0;
        Height = 0;
        GC.Collect();
    }
}

SystemOutOfMemoryException发生在指令new Byte[Length]。我认为这是我创造了太多阵列,但我不知道该怎么做。

1 个答案:

答案 0 :(得分:1)

主要问题是listImagesStart会保留每个startImg项的引用。这将使GC不会释放由myImg.LoadImage(使用数组矩阵)分配的内存。

快速解决方案:您可以将Matrix设置为null以回收内存。

public void UnLoadImage()
{
      Matrix = null ; // this will allow GC to recycle memory used by Matrix
}

然后(我删除了无用的docontinue变量):

try
{
    startImg.LoadImage(_baseFileResults);

    //Save image as file
    startImg.Save();

    // Do rotate
    MyImg lastRotate = baseImg;
    MyImg imgtmp;
    String[] tabRotate = new String[3] { "_90", "_180", "_270"};
    foreach (String rotate in tabRotate)
    {
        imgtmp = new GenImg(baseImg.FileName + rotate + baseImg.FileExtension);
        imgtmp.LoadImage(lastRotate);
        imgtmp.Rotate90();
        imgtmp.Save();
        lastRotate = imgtmp;
    }

    startImg.Dispose();
    imgtmp.Dispose();
}
catch
{

}
finally
{
      startImg.Unload(); // Here is the trick
}