2017-02-13 32 views
0

我正在處理用於處理圖像的C#中的軟件。我有很多圖片(11000),當我幾分鐘後執行我的計劃,我有一個「OutOfMemoryException異常」的在循環中創建數組引發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]。我認爲這是我創建了太多陣列,但我不知道該怎麼做。

+0

在你的foreach循環調用imgtmp.LoadImage以及Rotate90都alllocate內存。這是你正在處理11000圖像的循環嗎?另外,您不會提到每張圖片的大小。您在離開此循環之後纔會調用處置。而這個foreach循環在一個平行的範圍內。您應該重新考慮如何調用Dispose。 –

+0

@DaveS我正在'Parallel.Foreach'中處理我的11000張圖片,列表是'listImagesStart'。圖像是700x700像素。如果docontinue爲false,我修改了我的代碼來調用Dispose。 (我在等待結果) –

回答

1

主要問題是listImagesStart保持參考每個startImg項目。這將使GC不會釋放由myImg.LoadImage(與Matrix陣列)分配的內存。

快速解決方案:您可以將矩陣設置爲空以回收內存。

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 
} 
+0

是否可以調用我的'Dispose'而不是'UnLoadImage'?我的Dispose做'Matrix = null' –

+0

你可以自由地將UnloadImage重命名爲Dispose()並實現IDisposable – Ksv3n

+0

請評論你爲什麼downvoted? – Ksv3n