2017-07-27 9 views
2

Visual StudioのC#アプリケーションで写真をダウンロードし、回転などの操作をいくつか行い、外部のHDに新しい画像をフリップして保存します。実行中にメモリなしのアプリケーション

私は同じ仕事をしているいくつかのスレッドがあります。

アプリが数時間実行されているときに、ストレージメモリが不足していることを示す例外が発生します。

次の図は、アプリの起動時のプロセスメモリを示していますが、しばらく実行していた場合、そのメモリは3Gbまで増加します。私は上のすべてのストリーム、memorystreams、ビットマップ、インスタンスを終了し、プログラムで

enter image description here

。 問題は、実行中にメモリを解放するか、メモリの増加を回避する方法ですか?

try 
{ 
    request = (HttpWebRequest)WebRequest.Create(new Uri(this._url, UriKind.Absolute)); 
    request.UserAgent = UserAgent.get_user_agent(); 
    noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); 
    request.CachePolicy = noCachePolicy; 
    response = request.GetResponse(); 
    responseStream = response.GetResponseStream(); 
    reader = new BinaryReader(responseStream); 
    memoryStream = new MemoryStream(); 

    byte[] bytebuffer = new byte[BytesToRead]; 
    int bytesRead = reader.Read(bytebuffer, 0, BytesToRead); 

    while (bytesRead > 0) 
    { 
     memoryStream.Write(bytebuffer, 0, bytesRead); 
     bytesRead = reader.Read(bytebuffer, 0, BytesToRead); 
    } 

    image.BeginInit(); 
    memoryStream.Seek(0, SeekOrigin.Begin); 

    image.StreamSource = memoryStream; 
    image.EndInit(); 

    if (image.Width < 100 || image.Height < 50) 
    { 
     _parent.working_image = "Error procesado imagen"; 
     _parent.isWorking = false;               
     return false; 
    }    

    Bitmap image_rotated = CropImage(RotateFlipImage(BitmapImage2Bitmap(image)));    
    if (image_rotated == null)    
    {    
     _parent.working_image = "Error procesado imagen"; 
     _parent.isWorking = false; 
     return false; 
    } 

    BitmapFrame image200 = CreateResizedImage(Bitmap2BitmapImage(image_rotated), "large"); 
    BitmapFrame image100 = CreateResizedImage(Bitmap2BitmapImage(image_rotated), "short"); 

    // Directorio 
    int directory_main = (int)(this._Id/10000); 

    // Generamos la imagen de 200px   
    JpegBitmapEncoder encoder = new JpegBitmapEncoder(); 
    String photolocation = @"D:\hilo_" + hilo + "_200.jpg"; //file name     
    encoder.Frames.Add(BitmapFrame.Create(image200)); 
    FileStream filestream = null; 

    try 
    { 
     using (filestream = new FileStream(photolocation, FileMode.Create)) 
     { 
      encoder.Save(filestream); 
     } 

     // creamos directorio si no existe 
     System.IO.Directory.CreateDirectory(@"D:\backoffice\originales\" + directory_main + @"\" + this._Id); 
     if (!this.saveImage(photolocation, @"D:\backoffice\originales\" + directory_main + @"\" + this._Id + @"\" + _filename + "_200.jpg")) 
     { 
      _parent.working_image = "Error procesado imagen"; 
      _parent.isWorking = false; 
      image = null; 
      memoryStream.Close(); 
      filestream.Close(); 
      System.GC.Collect(); 
      System.GC.WaitForPendingFinalizers(); 
      return false; 
     } 

     filestream.Close(); 

     // Generamos la imagen de 100px 
     encoder = new JpegBitmapEncoder(); 
     photolocation = @"D:\hilo_" + hilo + "_100.jpg"; //file name 
     encoder.Frames.Add(BitmapFrame.Create(image100)); 

     using (filestream = new FileStream(photolocation, FileMode.Create)) 
     { 
      encoder.Save(filestream); 
     } 

     // creamos directorio si no existe 
     if (!this.saveImage(photolocation, @"D:\backoffice\originales\" + directory_main + @"\" + this._Id + @"\" + _filename + "_100.jpg")) 
     { 
      _parent.working_image = "Error procesado imagen"; 
      _parent.isWorking = false; 
      image = null; 
      memoryStream.Close(); 
      filestream.Close(); 
      System.GC.Collect(); 
      System.GC.WaitForPendingFinalizers(); 
      return false; 
     } 

     filestream.Close(); 
     encoder = null; 
     image100 = null; 
     image200 = null; 

     SqlConnection con = new SqlConnection(@"Data Source=DESKTOP-UC7AQ3V\SQLEXPRESS;Integrated Security=SSPI;User ID=frank;password=jungla"); 
     SqlCommand cmd = new SqlCommand("UPDATE dbo.image_objects_download_log SET locked=0, worked=1, isWorking=1 WHERE [email protected]", con); 
     cmd.Parameters.AddWithValue("@id", Id); 
     con.Open(); 
     cmd.ExecuteNonQuery(); 
     cmd.Dispose(); 
     con.Close(); 
     _parent.working_image = "Trabajo finalizado con éxito"; 
     _parent.isWorking = false; 
     image = null; 
     memoryStream.Close(); 
     System.GC.Collect(); 
     System.GC.WaitForPendingFinalizers(); 
     return true; 
    } 
    catch (IOException e) 
    { 
     Console.WriteLine("---------> " + e.Message); 
     _parent.working_image = "Error procesado imagen"; 
     _parent.isWorking = false; 
     image = null; 
     memoryStream.Close(); 
     filestream.Close(); 
     System.GC.Collect(); 
     System.GC.WaitForPendingFinalizers(); 
     return false; 
    } 
    catch (UriFormatException e) 
    { 
     _parent.working_image = "Error procesado imagen"; 
     _parent.isWorking = false; 
     image = null; 
     memoryStream.Close(); 
     filestream.Close(); 
     System.GC.Collect(); 
     System.GC.WaitForPendingFinalizers(); 
     return false; 
    } 
}    
+1

メモリを噛んでいるコードを表示する必要があります –

+0

私は今、アプリケーションを実行しています。例外が発生すると、私は写真を撮ります。 – Apalabrados

+0

これらのオブジェクトも処分しますか? –

答えて

2

私はusingブロックにIDisposableを実装するすべてのオブジェクトをラップするためにあなたをお勧めします。

try 
{ 
    request = (HttpWebRequest)WebRequest.Create(new Uri(this._url, UriKind.Absolute)); 
    request.UserAgent = UserAgent.get_user_agent(); 
    noCachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore); 
    request.CachePolicy = noCachePolicy; 

    (WebResponse response = request.GetResponse()) 
    { 
      // Rest of your code inside here 
    } 
} 

これは、使用する画像リソースで特に重要です。

BitmapFrame image200 = null; 
BitmapFrame image100 = null; 

using(Bitmap image_rotated = CropImage(RotateFlipImage(BitmapImage2Bitmap(image)))) 
{ 
    if (image_rotated == null) 
    { 
      _parent.working_image = "Error procesado imagen"; 
      _parent.isWorking = false; 
      return false; 
    } 

    image200 = CreateResizedImage(Bitmap2BitmapImage(image_rotated), "large"); 
    image100 = CreateResizedImage(Bitmap2BitmapImage(image_rotated), "short"); 
} 

また、あなたはビットマップ、BitmapFramesや画像の処分されていない方法Bitmap2BitmapImage

+0

Opはディスポーザブルを正しく処分しているようですが、 –

+0

@EmrahSüngü 'image_rotated'の処分は表示されません。例えば –

+0

ああ、' Bitmap'は処分されていません! –

1

をチェックする必要があります。画像をどこに作成しているのか分かりませんが、ローカルで作成することをお勧めします。処理が完了したら、ローカルで処理することができます。

ビットマップとイメージのローカル作成をUsingステートメントにラップします。このステートメントは、実行直後にオブジェクトを破棄します。この質問は、あなたはまた、あなたの画像オブジェクト上のDispose()を呼び出すことができます。この

Right way to dispose Image/Bitmap and PictureBox

または

の詳細を持っています。イメージをローカルに作成して、それを終了した時点でイメージを破棄してみてください。

Finalize()メソッドを使用して、BitmapFrameのリソースをクリーンアップします。

イメージオブジェクトに対してDisposeを呼び出すこともできます。イメージをローカルに作成して、それを終了した時点でイメージを破棄してみてください。

+0

私たちは私たち自身でFinalize()メソッドを呼び出すはずがないと思いますか?私は確信していません –

+0

@EmrahSüngüローカル変数を作成し、それを使用ブロックにラップする方が良いと思います –

関連する問題