How to delete files in memory left by the MemoryStream, with C #?

0

It turns out that I use MemoryStream to read a file with ReadToEnd in the following way:

IEnumerable<uint> uids = Client.Search(SearchCondition.Unseen());
IEnumerable<MailMessage> messages = Client.GetMessages(uids, FetchOptions.Normal);
 foreach (MailMessage msg in messages){

  foreach (Attachment atc in msg.Attachments){
     byte[] allBytes = new byte[msg.Attachments[0].ContentStream.Length];
     int bytesRead = msg.Attachments[0].ContentStream.Read(allBytes, 0, (int)msg.Attachments[0].ContentStream.Length);

     MemoryStream memory = new MemoryStream(allBytes);                          
     System.IO.StreamReader archivoXML = new System.IO.StreamReader(memory);
     memory.Close();
     String archivoXML_texto = archivoXML.ReadToEnd();
     archivoXML.Close();
  }

}

Because of this, I have the concern that in memory there could be several garbage files. If so, I would like to know how to erase or clean the memory of these files after reading them, where they are obtained with MemoryStream .

Observation: I read the attachment from an email using the IMAP protocol, and not from a saved route.

Observation 2: When using this instruction, read me content, if not, the variable XMLX_text stored empty:

 int bytesRead = msg.Attachments[0].ContentStream.Read(allBytes, 0, (int)msg.Attachments[0].ContentStream.Length);
    
asked by Danilo 29.12.2016 в 14:41
source

2 answers

1

C # uses automatic memory management. This is done by the Garbage Collector.

For your case it is not advisable to use the garbage collector but if you still decide to call it you can use the methods of the class System.GC

GC.Collect();
GC.WaitForPendingFinalizers();

The MemoryStream and StreamReader classes implement the IDisposable interface that contains the Dispose method that is used to free resources and be eligible by the garbage collector. So you can declare them within a using block by ensuring that the Dispose method is invoked or a try catch finally block

byte[] allBytes = new byte[msg.Attachments[0].ContentStream.Length];   

using( MemoryStream memory = new MemoryStream(allBytes),
       StreamReader archivoXML = new StreamReader(memory))
{ 
   String archivoXML_texto = archivoXML.ReadToEnd();
}
    
answered by 29.12.2016 в 20:06
0

Regarding your primary question, in .NET , there is usually no need to worry about recovering memory. .NET includes a garbage collector that automatically and periodically detects structures in memory that the program no longer needs and collects .

So, unless you're doing something very advanced, do not worry about recovering the lost memory. That will be done automatically.

Now, although the aspect of memory is not a problem, your program definitely has other problems that do require your attention:

  • You should always use the Stream classes in using blocks so that the Dispose runs automatically, even if an exception is thrown.
  • Despite reading each attachment in a cycle, you are only referring to the first attachment with the following expression (note the index [0] ): msg.Attachments[0].ContentStream.Length .
  • (this point no longer applies since you edited the code in your question) The most serious problem is that you never read the content of the attachments! When you create the fix allBytes ( byte[] allBytes = new byte[msg.Attachments[0].ContentStream.Length]; ), the only thing you are doing is to give the length equivalent to the content of the attachment, but the content itself are pure zeros.
  • There is no need to use an intermediary array of bytes. You can pass ContentStream directly to StreamReader .
  • With all these points in mind, the code should look more like the following:

    foreach (Attachment atc in msg.Attachments)
    {
        using (var streamReader = new StreamReader(atc.ContentStream))
        {
            String archivoXML_texto = streamReader.ReadToEnd();
            // hacer algo con la cadena...
        }
    }
    
        
    answered by 30.12.2016 в 01:39