Is this code needed, or because the UnLoad event of the page disposes all controls on page anyway there's no point in writing such code:
fu.PostedFile.InputStream.Flush();
fu.PostedFile.InputStream.Close();
fu.FileContent.Dispose();
I'm asking because on examples from msdn I see that they write code like
FileUpload1.SaveAs(savePath);
but don't ever bother to dispose the stream afterwards, but on the hand I see some people do explicitly dispose the input stream after saving?
Official guidance suggests that there is no need to dispose this stream, as it will be disposed when request processing ends:
Server resources that are allocated to buffer the uploaded file will be destroyed when the request ends. To save a durable copy of the file, use the SaveAs method.
To back this up I also did a bit of code digging through the sources. Turns out that neither FileUpload nor HttpPostedFile are responsible for disposing this stream. In fact they themselves do not hold any resources at all, and just provide an interface to access parts of the request.
HttpRequest does some disposal. But not all disposable objects are being disposed. Here is its Dispose:
/*
* Cleanup code
*/
internal void Dispose() {
if (_serverVariables != null)
_serverVariables.Dispose(); // disconnect from request
if (_rawContent != null)
_rawContent.Dispose(); // remove temp file with uploaded content
}
What is not disposed however is the collection HttpRequest.Files, which the upload controls interface. To fill this collection up with data every posted file is wrapped into an HttpPostedFile object, and an HttpInputStream is created for each. This stream object holds the reference to the whole data (see rawContent above) and knows about offset and length of relevant file part. It is worth noting that HttpInputStream implements IDisposable, however I wasn't able to find the code that disposes these stream objects.
To sum it up:
Upload controls do not dispose the stream
Request or HttpContext do not dispose the stream either
However Request disposes the underlying data
So it looks like the idea here is that when request processing is finished, references to the relevant data will be dropped and it will be disposed. So it won't hurt to manually dispose the stream you've used, but it is also not necessary.
Related
I have a StreamWriter which underlying stream is a FileStream. Will the following code guarantee that the FileStream also flushes its buffer into the actual file on the file system, or do I need to explicitly call Flush() on the FileStream?
using (var fs = new FileStream("blabla", FileMode.Append)) {
using (var sw = new StreamWriter(fs)) {
sw.WriteLine("Hello, I want to be flushed.");
sw.Flush(); //I need this to also flush onto the file, not just to the FileStream
}
}
As per MSDN, "Flushing the stream will not flush its underlying encoder unless you explicitly call Flush or Close", but I do not know if a FileStream can be considered an "underlying encoder".
Also, if I don't specify FileOptions.WriteThrough, am I guaranteed that the OS will eventually write the flushed line onto the disk even if the program crashes before the two streams have been closed (assuming for example no using {} blocks, only a call to Flush())?
In my scenario I need to leave the stream open (for logging) so I cannot use using {} blocks, but I would like to make sure data will always be written to the disk even if the program crashes. I can afford to lose data if there is a power shutdown and the OS has not flushed onto the disk, but otherwise I need the OS to eventually flush even if I never properly call Close() on the stream.
Yes, calling Flush on StreamWriter will cause the underlying stream to be Flushed. The 4.5 version calls a private Flush(bool,bool) function, which ends with:
if (flushStream)
{
this.stream.Flush();
}
Where flushStream is the first parameter, this.stream is the stream that the StreamWriter was constructed on, and the call in Flush() is Flush(true,true).
(Older parts of answer - I was being very roundabout in answering. Moved most relevant part of answer to top)
It's not explicitly spelled out in the documentation anywhere I can find it, but any stream class that is constructed by passing it another stream should be assumed to "take ownership" of that stream (unless it's specifically called out otherwise).
That is, once you've constructed the StreamWriter using fs, you shouldn't perform any direct actions on fs yourself.
The part you quoted from MSDN relates to the later sentences:
This allows the encoder to keep its state (partial characters) so that it can encode the next block of characters correctly. This scenario affects UTF8 and UTF7 where certain characters can only be encoded after the encoder receives the adjacent character or characters.
That is, you may have passed data to Write such that you've given it some Unicode surrogates, but not a complete character. Flush will not write those surrogates to the stream. So long as you're always passing well formed (complete) strings to Write, you do not need to concern yourself about this.
Streams disposal is guaranteed if used with using block!
With a chain of streams,closing the outermost stream(at the head of the chain) i.e StreamWriter in your case closes the whole lot i.e FileStream
Flush method forces internal buffer to be written immediately.Flush is automatically called when stream is closed,so you never need to do the following
s.Flush();s.Close();
So,the moment the most topmost stream is closed it flushes and then closes it underlying streams who also flush there content.
For example consider this chain
FileStream->GZipStream->StreamWriter
So,the moment you close the StreamWriter
StreamWriter flushes and closes.It also closes undelying GZipStream
GzipStream flushes and closes.It also closes underlying FileStream
FileStream flushes and closes
Can anyone explain why not calling Dispose() explicitly, and native resource still gets cleaned up. Does it get called implicitly?
I came cross below
calling Dispose is not required to guarantee native resource cleanup.
Native resource cleanup will always happen eventually; calling
Dispose lets you control when that cleanup happens.
// Create the bytes to write to the temporary file.
Byte[] bytesToWrite = new Byte[] { 1, 2, 3, 4, 5 };
// Create the temporary file.
FileStream fs = new FileStream("Temp.dat", FileMode.Create);
// Write the bytes to the temporary file.
fs.Write(bytesToWrite, 0, bytesToWrite.Length);
// Explicitly close the file when finished writing to it.
//fs.Dispose();
Dispose should be called explicitly in code within finally block or via using statement.
FileStream contains Finalize method which calls Dispose inside:
~FileStream()
{
if (_handle != null) {
BCLDebug.Correctness(_handle.IsClosed, "You didn't close a FileStream & it got finalized. Name: \""+_fileName+"\"");
Dispose(false);
}
}
Which means it will be eventually called by Finalizer when the object will not be longer reachable. Of course, it is good to call Dispose explictly as it let's you control cleanup deterministicaly as you've mentioned.
The garbageCollector is cleaning up unreferenced Objects, when it gets resources of the OS, but if you have a highly frequented Application it might be useful not to have to wait for it, because otherwise your memory gets filled up. Then the usage of Dispose is quite necessary.
Update:
The objects do not even need to implement IDisposable to be cleaned up, because it's the Finalize-Method that is called.
I was playing around with MailKit/MimeKit and something is bugging me. I wanted to send e-mails with attachments using streams. MimeKit offers the BodyBuilderclass which makes it very easy to create the body message and attach files:
public void SendEmail(string body, Stream attachment, string fileName)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Carl", "carl#site.com"));
message.To.Add(new MailboxAddress("Rick", "rick#site.com"));
message.Subject = "Things got messy...?";
var builder = new BodyBuilder();
builder.TextBody = body;
builder.Attachments.Add(fileName, attachment);
message.Body = builder.ToMessageBody();
using (var client = new SmtpClient())
{
// code to send e-mail here...
}
}
I generate the stream elsewhere in my code and I don't close it, so I can pass it on to MimeKit. The thing that is not clear is: Do MimeKit disposes the stream? Basically (as far as I'm aware) the consumer usually is the responsible for disposing Streams. I'm also aware that calling dispose on a MemoryStream (which I'm using basically) won't free up any resources.. but will prevent from reading/writing to it. But if, in the future, the implementations change to another type of Stream, things can get more complex.
I also dig into MikeKit source code, and found that the Stream passed in to the AttachmentCollection.Add gets 'added' into a MemoryBlockStream which inherits from Stream (and implements Dispose) so I'm supposing it get's disposed but, at this point, I'm just guessing.
Any ideas?
By inspecting the code on MimeKit. Specifically the two overloads:
1 - Overload that takes byte[] data, you can see that they create a stream and keep the ownership of it. That's done by creating the stream on a using block. One can assume already that the code downstream (CreateAttachment()) is not handling any Stream dispose.
2 - The overload that you mention, the stream is just passed through to CreateAttachment().
I'd say that in this case you're better off disposing it yourself if you can. That is, if it can be done only once the stream has been consumed.
In fact, after calling Add, your Stream was already consumed. All data will sit in memory once the method returns and you could dispose your stream. You can see this on LoadContent().
Just as you don't want to avoid calling Dispose because you have a MemoryStream knowingly that another stream that requires Dispose could be used later. Disposing your Stream after calling Add could be a bad idea.
In case the behavior of the library changes in the future and at the time of the call to Add your stream is not consumed yet (which would be the expected behavior in my opinion).
The stream would only be Read at the time of writing the data to the NetworkSocket. In fact Streaming data, without loading it all in RAM.
In such case you'd only be able to Dispose the Stream after the Mailkit.Send was called.
You don't need to dispose those streams. You can if you want, but it's not necessary.
I have a logger class thats a singleton. In it's destructor I call Close() which prints the footer for the log and then closes the StreamWriter.
public void Close()
{
WriteLogFileFooter();
_logFile.Flush();
_logFile.Close();
}
The problem is when System.Enviornment.Exit(1) is called from elsewhere in the program (portions that I didn't write myself), the footer is never printed and my logger throws an exception for trying to write to a closed stream. I can only assume the Exit command is causing my StreamWriter to be closed before my Singleton is destructed. I tried to use GC.SupressFinalize() on my StreamWriter but that didn't seem to help.
You are violating one explicit rule for finalizers:
The Finalize method should not reference any other objects.
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=VS.90).aspx
It's entirely possible that the managed object you hold a reference to is collected before your object is collected when the application exits.
UPDATE
If you need to clean up managed resources when the application exits, you could hook up the ProcessExit event of AppDomain rather than rely on non-deterministic behavior of finalizer execution.
.NET Console Application Exit Event
You should make your logger implement IDisposable, and use it in a using block. This means that it will be deterministically disposed, whereas now it is being nondeterministically destructed.
The cause of the error is that your stream will sometimes be closed before the logger, as Exit basically destroys everything (nondeterministically) and quits. You should use a deterministic pattern (IDisposable) to avoid this.
In reality, destructors are rarely useful in C#, for the precise reason that they are non-deterministic. They only are worth using for releasing unmanaged resources.
Also, implementing IDisposable may make it inconvenient to use a singleton. I personally think it's better to create an instance to be used throughout the program and disposed at the end, rather than an explicit singleton.
As others have already clearly stated, you should not attempt to access your _logFile object at all from your logger class' finalizer. You shouldn't access any other objects in a finalizer, because the Garbage Collector might already have wiped them out of existence.
I think you could avoid your problem by a few simple steps:
Get rid of your current finalizer.
Perform a _logFile.Flush after every single write, instead of waiting until the very end of your logger object's lifetime when it might already be too late.
Flushing a log file stream frequently seems legitimate to me because the whole point of having a log is using it to find, and deal with, situations where errors have occurred. If your process is suddenly terminated by an exceptional situation, your log should still be as complete as possible; thus flushing the log stream buffer frequently seems a sensible thing to do.
Make your logger implement IDisposable (this MSDN Magazine article will explain to you how this is done) and close your log file stream from there.
I had the same problems and my solution was as follows:
When creating the FileStream in the constructor of your class used GC.SuppressFinalize immediately. This makes you responsible for cleaning the stream
Close the stream in the Dispose() of the class
public class LogFileEventListener : IDisposable
{
private bool disposed = false;
private FileStream fileStream;
public LogFileEventListener(string path)
{
//Opens a new file stream to log file
this.fileStream = new FileStream(path, FileMode.Append, FileAccess.Write);
GC.SuppressFinalize(this.fileStream);
}
/// <summary>Finalize the listener</summary>
~LogFileEventListener() { this.Dispose(); }
/// <summary>Disposes the listener</summary>
public override void Dispose()
{
try
{
if (!this.disposed)
{
/* Do you stuff */
//Close the log file
if (this.fileStream != null)
{
this.fileStream.Close();
this.fileStream = null;
}
base.Dispose();
}
}
finally
{
this.disposed = true;
GC.SuppressFinalize(this);
}
}
}
Most likely the StreamWriter is being closed else where.
Try creating an additional StreamWriter in your singleton's constructor, write to it a few times (to confirm that it is working), then write to it again in the destructor before calling close (close will also flush).
If the above works then you will know some other code is closing your log. If it does not work then you will know that it is a .NET thing (possibly having something to do with how/where the variable is referenced).
According to the documentation, you should be able to work around the issue by putting the StreamWriter in a base class. This of course will not work for you because your test case is not a standard finalization, but is a program exit, meaning .NET does what it wants when it wants. Instead, you should catch the exit event, dispose of this class, then return, to guarantee that things are disposed in the correct order. You should also check if the StreamWriter is already closed in the finalizer in case the program aborts due to an error.
I have some doubt about BackgroundTransferRequest RAM efficiency, or more probably, I'm missing something.
BackgroundTransferRequest should initialize a web request (GET by default) and then store the response to IsolatedStorage specified by DownloadLocation, so we shouldn't have any stream opened containing the result, we just have the physical file in the IsolatedStorage.
Simple, Easy, Efficient.
Then, why after 200 succeeded Downloads I still have 42k occupied ram?
Of course If I restart the application I have 1k occupied ram and previously downloaded files are still on the Isolated Storage, so we probably have something on the BackgroundTransferRequest that occupies ram and never free it, despite the dispose call.
Please correct me If I'm doing something wrong.
Below you can see the code snippet used for adding and removing transfers.
INITIALIZING TRANSFER
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transfer.TransferUri);
transfer.RequestId = transferRequest.RequestId;
transferRequest.DownloadLocation = transfer.DestinationUri;
transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
BackgroundTransferService.Add(transferRequest);
ONCE DONE, REMOVE TRANSFER
BackgroundTransferRequest transferToRemove = BackgroundTransferService.Find(transferID);
if (transferToRemove != null)
{
BackgroundTransferService.Remove(transferToRemove);
transferToRemove.Dispose();
transferToRemove = null;
}
Thanks you very much!
When using the BackgroundTransferService class you have to be very careful with references to the BackgroundTransferRequest objects to avoid memory leaks.
_BackgroundRequests = BackgroundTransferService.Requests;
The previous assignment will create new references to the BackgroundTransferRequest objects, thus you should always dispose of the existing ones to avoid memory leaks.
If in your code you keep a local reference to the BackgroundTransferService.Requests list, then you should always dispose of the old references when using the Requests property.
foreach(var Request in _BackgroundRequests)
{
Request.Dispose();
}
_BackgroundRequests = BackgroundTransferService.Requests;
Since the BackgroundTransferService allows a maximum of 5 BackgroundTransferRequest objects to be queued, one can be tempted to use the Count() method on the BackgroundTransferService.Requests list.
Remember that this will create new references and can cause memory leaks. The best solution would be to keep an internal counter of the current queued transfers or to never care about the number of queued transfer and handle the exception thrown by the service when too many requests are queued.
Finally, one should dispose of the BackgroundTransferRequest objects once they have been completed (successfully or not), but you already do so.