2017-02-13 1 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

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

は、(私は役に立たないdocontinue変数を削除しました)。 11000枚の画像を処理しているループですか?さらに、各画像の大きさについては言及していません。このループを離れるまで、処理を呼び出さないでください。そして、このforeachループは並列にあります。あなたはあなたのDisposeに電話する方法を再考する必要があります。 –

+0

@DaveS私は11000個の画像を 'Parallel.Foreach'で処理しています。リストは' listImagesStart'です。画像は700x700ピクセルです。 docontinueがfalseの場合、コードを変更してDisposeを呼び出しました。 (私は結果を待っています) –

答えて

1

主な問題は、listImagesStartがそれぞれstartImgアイテムの参照を保持していることです。これにより、GCがmyImg.LoadImage(配列マトリックスを使用)によって割り当てられたメモリを解放しなくなります。

簡単な解決策:行列をnullに設定してメモリをリサイクルすることができます。あなたは、両方のメモリをalllocate imgtmp.LoadImageなどRotate90を呼び出して、あなたのforeachループで

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

'UnLoadImage'の代わりに' Dispose'を呼び出すことは可能ですか?私のDisposeは 'Matrix = null'を実行します –

+0

UnloadImageの名前をDispose()に変更し、IDisposableを実装しています – Ksv3n

+0

なぜあなたはdownvotedをコメントしてください? – Ksv3n

関連する問題