执行期间没有内存的App

时间:2017-07-27 08:17:37

标签: c# visual-studio

我有一个Visual Studio c#app,其任务是下载图片,进行一些操作,如旋转和翻转,并将新图片存储在外部HD中。

我有几个线程做同样的工作。

当应用程序运行了几个小时后,会出现异常,表明存储内存不足。

下图显示了应用程序启动时的进程内存,但是当它运行一段时间后,这样的内存会增加到3Gb。

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 object_id=@id", 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;
    }
}              

2 个答案:

答案 0 :(得分:2)

我建议您在IDisposable块中包含实现using的所有对象。我将在代码的响应部分演示:

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

答案 1 :(得分:1)

您没有丢弃位图,BitmapFrame或图像。我不确定你在哪里创建你的图像,但我建议你在本地创建它 - 所以它可以在你完成处理后在本地处理。

在Using语句中包装本地创建的位图和图像,该语句将在执行后立即处理对象。这个问题有关于此的更多细节

Right way to dispose Image/Bitmap and PictureBox

您还可以在图像对象上调用Dispose()。尝试在本地创建图像并在完成后将其丢弃。

使用Finalize()方法清理BitmapFrame

的资源

您也可以在图像对象上调用Dispose。尝试在本地创建图像并在完成后将其丢弃。