2017-07-27 98 views
2

我有一個Visual Studio C#應用程序,它的任務是下載圖片,進行一些操作,如旋轉和翻轉和Finnaly將新圖片存儲在外部HD中。在執行過程中沒有內存的應用程序

我有幾個線程正在做同樣的工作。

當應用程序運行了幾個小時後,就會出現一個異常,表明缺少存儲空間。

下圖顯示了應用程序啓動時的進程內存,但當它運行一段時間後,此類內存增加到3Gb。

enter image description here

在我關閉所有流,memorystreams,位圖,實例等程序。 因此,問題是,如何在執行過程中釋放內存或避免內存增加?

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

我建議你換行實現在usingIDisposable所有對象。我會證明你的代碼的響應部分:

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"); 
} 

您也應該檢查方法Bitmap2BitmapImage

+0

歐普似乎正在妥善處置一次性用品,雖然 –

+0

@EmrahSüngü我沒有看到任何處置'image_rotated'例如 –

+0

啊是的'位圖'不處理! –

1

你是不是你的處置位圖,BitmapFrames或圖像的。我不確定你在創建圖像的位置,但是我建議在本地創建它 - 所以在完成處理後可以在本地處理它。

在Using語句中包裝位圖和圖像的本地創建,它將在執行後立即處理對象。這個問題有更多的細節該

Right way to dispose Image/Bitmap and PictureBox

你也可以在你的圖像對象調用Dispose()。嘗試在本地創建映像,並在完成後將其丟棄。使用Finalize()方法來清理BitmapFrame的資源。

您也可以在您的圖像對象上調用Dispose。嘗試在本地創建映像,並在完成後將其丟棄。

+0

我想我們不應該自己調用Finalize()方法嗎?我不知道 –

+0

@EmrahSüngü我認爲創建局部變量並將它們包裝在使用塊中會更好 –

相關問題