I want a method to return an unmanaged resource and later in the program dispose of that resource. Does the following implementation do what I intend ?
class DocxManager
{
// DocX is the unmanaged resource
public Docx createDocX(string pathToFile)
{
return new DocX(pathToFile);
}
public void makeChangesAndSaveDocX(DocX wordDoc)
{
wordDoc.Save();
// IS THIS WAY THE UNMANAGED RESOURCE FREED CORRECTLY AND NO MEMORY LEAK ?
((IDisposable)wordDoc).Dispose();
}
}
First off all, you seem to be misunderstanding the concept of managed and unmanaged resources. wordDoc is not an unmanaged resource, its a managed resource which happens to either directly hold an unmanaged resource or acts as a wrapper around some other IDisposable object (you don't care wich of the two is true). Its important you are clear on this because otherwise you will not implement correctly the IDisposable pattern when you need to. Read this for a very instructive answer on the subject and a few chuckles courtesy of Eric Lippert.
Does the following implementation do what I intend ?
No, it does not and to make things worse, the contract of DocXManager is simply horrible (more on that later).
What hapens if wordDoc.Save() throws and exception because the file is being used by another process, or maybe you've run out of space in the hard drive, or you've lost connection, etc.?
If the thrown exception is not recoverable (it's not handled anywhere in your code or it is but you will terminate it ASAP) then it's not really an issue and the runtime will clean up everything behind you when the process is terminated. On the other hand, if the exception is handled (warn the user the file is in use, the directory is not available, etc.) and the process keeps running then you've just maybe leaked a resource.
How to avoid this? Use a try-finally block:
public void makeChangesAndSaveDocX(DocX wordDoc)
{
try
{
wordDoc.Save();
}
finally
{
((IDisposable)wordDoc).Dispose();
}
}
Now you are sure that Dispose() will be called in any recoverable scenario.
So, is this good enough? Well....not exactly. The problem here is that makeChangesAndSaveDocX's (that should be MakeChangesAndSaveDocX by the way) contract is unclear. Who is responsible of disposing wordDoc? MakeChangesAndSaveDocX or the caller? Why one or the other? How does the consumer know that he doesn't need to worry about wordDoc once he's called MakeChangesAndSaveDocX? Or how is he supposed to know he can't use wordDoc after calling the public method MakeChangesAndSaveDocX? Why does DocXManager assume that the consumer will not need to use wordDoc after calling MakeChangesAndSaveDocX? Yuck...this is a mess.
I'd recommend you reconsider your approach and do one of the following:
If the method signature MakeChangesAndSaveDocX(DocX wordDoc) makes sense (somebody else can own wordDoc), then do not dispose wordDoc in MakeChangesAndSaveDocX. Let the caller carry that burden, he should be responsible because the object belongs to him not to MakeChangesAndSaveDocX.
If on the other hand, it makes no sense that somebody else who is not DocXManager owns wordDoc then wordDoc should be part of the state of DocXManager and you should reconsider the implementation of DocXManager to something allong the following lines:
public class DocXManager: IDisposable
{
private readonly DocX docX;
private bool disposed;
public DocXManager(string filePath)
{
docX = new DocX(filePath);
}
public void MakeChangesAndSaveDocX()
{
if (disposed)
throw new ObjectDisposedException();
docX.Save();
}
public void FrobDocX(Frobber frobber)
{
if (disposed)
throw new ObjectDisposedException();
frobber.Frob(docX);
}
public void Dispose()
{
if (disposed)
return;
Dispose(true);
disposed = true;
GC.SupressFinalize(this);
}
public void Dispose(bool disposing)
{
if (disposing)
{
//we can sefely dispose managed resources here
((IDisposable)docX).Dispose();
}
//unsafe to clean up managed resources here, only clean up unmanaged resources if any.
}
~DocXManager()
{
Dispose(false);
}
}
Now you've got a clear contract; DocManagerX is responsible of disposing correctly of DocX and the consumer is responsible of disposing correctly of any instance of DocManagerX he might use. Once responsibilities are clear, its easier to reason about code correctness and who should do what.
You'd use the manager in the following way:
using (var manager = new DocXManager(path))
{
manager.FrobDoxX(frobber);
manager.MakeChangesAndSaveDocX();
} //manager is guaranteed to be disposed at this point (ignoring scenarios where finally blocks are not executed; StackOverflowException, OutOfMemoryException, etc.)
Related
I want to encapsulate the process of unzipping a zip file, making the files available for use, and then automatically cleaning them up when they are no longer needed. I did this with a class that implements the IDisposable interface, so that I can instantiate it with "using" and the files will be cleaned up when going out of scope, eliminating the need to specifically delete the files. The class, TempUnzip, can therefore be used thus:
static void AccessZipFileContents(string zipFilePath)
{
using (var temp = new TempUnzip(zipFilePath)
{
var tempPath = temp.TempPath;
if (tempPath != null)
{
// read/use the files in tempPath
}
} // files automatically get deleted when it goes out of scope! Woohoo!
}
Here is the implementation of the TempUnzip class:
using System.IO;
using System.IO.Compression;
public class TempUnzip : IDisposable
{
public TempUnzip(string zipFilePath)
{
try
{
var tempFolderName = Path.GetRandomFileName();
var tempFolder = Path.GetTempPath();
var tempPath = Path.Combine(tempFolder, tempFolderName);
Directory.CreateDirectory(tempPath);
ZipFile.ExtractToDirectory(zipFilePath, tempPath);
TempPath = tempPath;
}
catch (Exception) { TempPath = null; }
}
public readonly string TempPath;
public void Dispose()
{
try
{
if (TempPath != null)
Directory.Delete(TempPath);
}
catch (Exception) { }
}
}
Is this a valid use of IDisposable?
If so, do I need to implement the full standard IDisposable pattern?
If not, is there a better way to encapsulate the creation and destruction of files in such a way that they're tied to the lifetime of an object, or should I avoid this altogether?
Is this a valid use of IDisposable?
From the documentation:
Provides a mechanism for releasing unmanaged resources.
Files on local disk are certainly unmanaged resources. Thus, this use fits with the stated purpose of IDisposable.
If so, do I need to implement the full standard IDisposable pattern?
You can. The usual cautions about finalizers need to be considered, but you already linked to those. It certainly won't hurt.
If not, is there a better way to encapsulate the creation and destruction of files in such a way that they're tied to the lifetime of an object, or should I avoid this altogether?
I also like a functional approach for this kind of problem. That would make your example look something like this:
static void AccessZipFileContents(string zipFilePath)
{
ZipManager.RunWithZipExtracted(zipFilePath, (string tempPath) =>
{
if (tempPath != null)
{
// read/use the files in tempPath
}
} // files automatically get deleted when it goes out of scope! Woohoo!
}
//from ZipManager.cs...
static void RunWithZipExtracted(string zipLocation, Action<string> toRun)
{
var tempPath = CalculateTempPath();
try
{
ExtractZip(zipLocation, tempPath);
toRun(tempPath);
}
finally
{
DeleteFolder(tempPath);
}
} //private methods left as exercise for the reader
A pattern like that avoids the problem of "what if they don't call Dispose?" entirely.
This is a situation where having a finalizer is probably a good idea, but the MS pattern is predicated on the idea of public objects having finalizers, which is almost always a bad idea. Instead, resources that will require finalization-based cleanup should be encapsulated in privately-held objects whose references are never exposed to the outside world. Because the inner objects are private, there's no need for them to use the IDisposable pattern--instead they may be designed in whatever fashion best fits the requirement.
Since trying to close a file handle more than once may have catastrophic consequences, and it's possible (though rare) for a finalizer to execute while other code is using an object (or even performing Dispose upon it!), writing a robust class can be difficult. A nasty issue that arises is that file accesses can block but finalizer actions shouldn't. One could work around that by creating a thread whose purpose was to wait until the file is supposed to be closed and deleted, and which would then close and delete the file. Even if the attempt to delete the file gets blocked, other finalizer actions could continue apace. Unfortunately, eagerly creating a thread for the purpose of allowing safe finalizer-based cleanup is apt to be a waste of resources, but thread creation seems like an excessively-heavyweight task to be performing within a finalizer. I don't know what the best solution is.
In this instance I would say that it is a good example of IDisposable, if Dispose isn't called straight away that you've finished using it then it's not the end of the world and quickly calling this for the same zip file wouldn't cause an exception as you're using unique temp folders each time; which again you're not leaving file pointers left open on the files, etc. The only issue I could see is that if disk space was really tight you might want to expose the delete folder as a method to allow the option of that being called directly and then Dispose is just used to clean up after for all cases.
Note: in this example you probably want to call Directory.Delete(TempPath, true); because the method you're calling will throw an IOException if the folder isn't empty (something your catch will hide) - see https://msdn.microsoft.com/en-us/library/62t64db3%28v=vs.110%29.aspx
I have the following logger-like class pattern:
public class DisposableClassWithStream : IDisposable
{
public DisposableClassWithStream()
{
stream = new FileStream("/tmp/file", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
writer = new StreamWriter(stream);
}
public void WriteLine(string s)
{
writer.WriteLine(s);
}
~DisposableClassWithStream()
{
Dispose();
}
private readonly object disposableLock = new object();
private bool isDisposed;
public void Dispose()
{
lock (disposableLock)
{
if (!isDisposed)
{
writer.Close();
stream.Close();
GC.SuppressFinalize(this);
isDisposed = true;
}
}
}
private FileStream stream;
private TextWriter writer;
}
and a very simple code using this class:
public static void Main(string[] args)
{
var t = new DisposableClassWithStream();
t.WriteLine("Test");
}
The code throws (nondeterministically), both on .net and mono, ObjectDisposedException caused by method Close of object writer as it tries to flush buffer to stream which is already disposed.
I understand that the reason is that GC finalizes stream before writer. How can I change the class pattern to be sure that stream is not disposed before the writer?
I tired to use GC.SuppressFinalize(writer) in the constructor, but I'm not sure if it is not too hacky.
Edit:
I would like to address the question of having finalizer in the first place. As mentioned at the beginning of the question, the class is used as a logger and I want to assure that all lines from writer are flushed to the hard disk before closing the process.
Do not create finalizer, unless your IDisposable implementation really works with unmanaged resources. FileStream and StreamWriter are managed resources.
Moreover, since SafeHandle was introduced, it is hard to imagine use-case, when any unmanaged resource couldn't be wrapped into managed SafeHandle. Do not follow blindly IDisposable implemetation from MSDN - it's OK, but it is intended for the case, when your type operates both managed and unmanaged resources.
Remove finalizer at all, and throw away GC.SuppressFinalize(this); from Dispose:
public void Dispose()
{
lock (disposableLock)
{
if (!isDisposed)
{
writer.Close();
stream.Close();
isDisposed = true;
}
}
}
Update.
Finalizers are intended for unmanaged resource cleanup.
You may consider finalizer as a place to close file handle, network socket, etc. This isn't a place for any application logic. In general, managed object during finalization resides in unusable state - there's no guarantee, that any of its IDisposables (like stream or writer in your sample) are not finalized already.
If you want to be sure, that particular log message is flushed into file, than write it and call writer.Flush(). Otherwise, if immediate flushing is undesirable for you, make sure, that you're calling dispose for the logger on application shutdown. Also note, that you can't protect from process termination, so don't be too paranoid with your logger.
Managed objects should not be cleaned up in the finalizer. The finalizer should only used for cleaning up unmanaged resources.
Rewrite your code as follows to dispose of managed resources when you are done with the streams.
public static void Main(string[] args)
{
using (var t = new DisposableClassWithStream())
{
t.WriteLine("Test");
}
}
And be sure to check out the Dispose Pattern article on MSDN
When a finalizer runs, most managed objects to which it holds references will meet one of the following criteria:
-1- Not care about cleanup, in which case the finalizer should do nothing with them.
-2- Be unable to perform cleanup in a thread-safe manner when invoked in the context of finalizer cleanup, in which case the finalizer should do nothing with them.
-3- Have already cleaned themselves up using their own finalizer, in which case the finalizer should do nothing with them.
-4- Have a Finalize method which hasn't run yet, but is scheduled to run at first opportunity, in which case the finalizer for the class holding the reference should do nothing with them.
Different objects will meet different criteria, and it may be difficult to know which of those criteria a particular object might meet, but for the vast majority of objects will meet any of the criteria, the required handling is the same: don't do anything with them in the finalizer.
There are a few rare scenarios involving things like weak events where finalizers may be able to do something useful with managed objects, but in nearly all such cases, the only classes which should have finalizers are those whose sole purpose is to managed the finalization cleanup of other intimately-related objects. If one doesn't understand all the wrinkles of finalization, including the differences between short and long weak references and how they interact with the finalizer, any finalizer one tries to write will likely do more harm than good.
Does the following psuedo code accomplish my goal of cleaning up after myself when my DLL is being hosted by code I don't control?
More specifically, how do I clean up my objects created in my static constructor?
Do I need to suppress Finalize in the Disposable?
Am I guaranteed that the compiler or something will call IDisposable even if the Host doesn't?
Psuedo code:
public class MyDLL : SomeHostICantControl, IDisposable
{
public SpinLock MyDictionarySpinlock = new Spinlock; // approximate syntax
public static Dictionary<string, string> MyDictionary = null;
public static Timer MyCleanUpTimer = null;
public static MyDLL()
{
// Set up Cache Here ... how do I dispose of it?
MyDictionary = new Dictionary<string, string>();
// remove old data from the dictionary, use spinlock to sync writes
// or use concurrent dictionary in .NET 4
MyCleanUpTimer = new Timer(); // run every hour
}
// many instances will be created and disposed of. I have no control when or how often
public void MyDll()
{
this.MyHostEvent += New Event Handler....
}
//.. some event handler code here
public void Dispose()
{
this.MyHostEvent -= Event Handler.;
// Do I need to suppressFinalize here?
}
//~MyDll()
//{
// Is this the right place to clean up after my constuctor?
//}
}
Answering your questions in order:
Static fields exist for the lifetime of the application, as such they are "cleaned up" as a result of the application exiting (memory is reclaimed, files are closed etc.). You don't appear to be doing anything that might require explicit action to be taken to clean-up (e.g. flushing buffered data in a StreamWriter to file), but perhaps there are details missing in your code snippet.
You need to suppress finalize in your Dispose() method if your class has a finalizer (yours appears not to as it's commented out), or if someone can derive from your class and may introduce unmanaged resources that may need cleaning up. The latter applies here as your class is not marked sealed, so you should suppress finalize in Dispose().
The runtime will not call Dispose(), however it will call the finalizer if one is present. Note however that as you class instances don't appear to be using any unmanaged resources, a finalizer should not be required.
I'm currently do a review of a C# app in which I see that :
public static bool ServiceExists(string servicename)
{
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController s in services)
{
if (s.ServiceName == servicename)
{
return true;
}
}
return false;
}
In this answer, Henk said that the non-use of Dispose() (or using) will not generate memory leaks, true or false?
Can I keep the previous code has it is or should I write someting like :
public static bool ServiceExists(string servicename)
{
ServiceController[] services = ServiceController.GetServices();
bool exists = false;
foreach (ServiceController s in services)
{
using(s)
{
if (s.ServiceName == servicename)
{
exists = true;
}
}
}
return exists;
}
What are the risks to no using Dispose() (or using) in this case?
A correctly written object shouldn't cause a memory leak if it's Dispose method isn't called. These days a .Net object which controls unmanaged resources should be doing so via a SafeHandle instance. These will ensure the native memory is freed even if Dispose is not called.
However it's very possible for objects which aren't written correctly to produce memory leaks if Dispose isn't called. I've seen many examples of such objects.
In general though if you are using an IDisposable instance which you own you should always call Dispose. Even if the object is correctly written it's to your benefit that unmanaged resources get cleaned up earlier instead of later.
EDIT
As James pointed out in the comments there is one case where not calling Dispose could cause a memory leak. Some objects use the Dispose callback to unhook from long lived events which if they stayed attached to would cause the object to reside in memory and constitute a leak. Yet another reason to always call Dispose
It all depends on what ServiceController.GetServices() is doing. If it is creating new instances of ServiceControllers when it is called, then it could cause a memory leak depending on what it needs to do (the ServiceController) in its Dispose method.
That said, adding 'using' in this case wouldn't fix it anyway as if you DID need to call dispose (implicitly via 'using' in this case) on each instance, it WOULDN'T as it returns whenever it finds a ServiceController with a matching name.
Therefore, if your first iteration found a matching ServiceController, all the other ServiceControllers wouldn't get disposed of anyway.
If I have the following situation:
StreamWriter MySW = null;
try
{
Stream MyStream = new FileStream("asdf.txt");
MySW = new StreamWriter(MyStream);
MySW.Write("blah");
}
finally
{
if (MySW != null)
{
MySW.Flush();
MySW.Close();
MySW.Dispose();
}
}
Can I just call MySW.Dispose() and skip the Close even though it is provided? Are there any Stream implimentations that don't work as expected (Like CryptoStream)?
If not, then is the following just bad code:
using (StreamWriter MySW = new StreamWriter(MyStream))
{
MySW.Write("Blah");
}
Can I just call MySW.Dispose() and
skip the Close even though it is
provided?
Yes, that’s what it’s for.
Are there any Stream implementations
that don't work as expected (Like
CryptoStream)?
It is safe to assume that if an object implements IDisposable, it will dispose of itself properly.
If it doesn’t, then that would be a bug.
If not, then is the following just bad
code:
No, that code is the recommended way of dealing with objects that implement IDisposable.
More excellent information is in the accepted answer to Close and Dispose - which to call?
I used Reflector and found that System.IO.Stream.Dispose looks like this:
public void Dispose()
{
this.Close();
}
As Daniel Bruckner mentioned, Dispose() and Close() are effectively the same thing.
However Stream does NOT call Flush() when it is disposed/closed. FileStream (and I assume any other Stream with a caching mechanism) does call Flush() when disposed.
If you are extending Stream, or MemoryStream etc. you will need to implement a call to Flush() when disposed/closed if it is necessary.
All standard Streams (FileStream, CryptoStream) will attempt to flush when closed/disposed. I think you can rely on this for any Microsoft stream implementations.
As a result, Close/Dispose can throw an exception if the flush fails.
In fact IIRC there was a bug in the .NET 1.0 implementation of FileStream in that it would fail to release the file handle if the flush throws an exception. This was fixed in .NET 1.1 by adding a try/finally block to the Dispose(boolean) method.
Both StreamWriter.Dispose() and Stream.Dispose() release all resources held by the objects. Both of them close the underlying stream.
The source code of Stream.Dispose() (note that this is implementation details so don't rely on it):
public void Dispose()
{
this.Close();
}
StreamWriter.Dispose() (same as with Stream.Dispose()):
protected override void Dispose(bool disposing)
{
try
{
// Not relevant things
}
finally
{
if (this.Closable && (this.stream != null))
{
try
{
if (disposing)
{
this.stream.Close();
}
}
finally
{
// Not relevant things
}
}
}
}
Still, I usually implicitly close streams/streamwriters before disposing them - I think it looks cleaner.
For objects that need to be manually closed, every effort should be made to create the object in a using block.
//Cannot access 'stream'
using (FileStream stream = File.Open ("c:\\test.bin"))
{
//Do work on 'stream'
} // 'stream' is closed and disposed of even if there is an exception escaping this block
// Cannot access 'stream'
In this way one can never incorrectly access 'stream' out of the context of the using clause and the file is always closed.
I looked in the .net source for the Stream class, it had the following which would suggest that yes you can...
// Stream used to require that all cleanup logic went into Close(),
// which was thought up before we invented IDisposable. However, we
// need to follow the IDisposable pattern so that users can write
// sensible subclasses without needing to inspect all their base
// classes, and without worrying about version brittleness, from a
// base class switching to the Dispose pattern. We're moving
// Stream to the Dispose(bool) pattern - that's where all subclasses
// should put their cleanup starting in V2.
public virtual void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Close();
}
Stream.Close is implemented by a call to Stream.Dispose or vice versa - so the methods are equivalent. Stream.Close exists just because closing a stream sounds more natural than disposing a stream.
Besides you should try to avoid explicit calls to this methods and use the using statement instead in order to get correct exception handling for free.