Accessing ConcurrentDictionary in destructor - c#

I have a Wrapper<T> where T : class that wraps around my objects. I store WeakReference<Wrapper<T>> in a ConcurrentDictionary, to implement weakly-referenced thread-safe cache for immutable objects that gets automatically cleaned up when memory is required for something else. I need to call ConcurrentDictionary.TryRemove in the Wrapper destructor to free the weak references in the dictionary that no longer point to a valid object.
It is well-known that we should not use any locking inside destructors because of the risk of dead-lock. So I wonder, can I use ConcurrentDictionary.TryRemove safely in a destructor? I am afraid it might have been implemented using SpinLock or some other tool and thus still presents a risk of dead-lock when used in destructor.

You can see the implementation of the ConcurrentDictionary at this location and the TryRemove implementation uses 'lock(...)'.
What you could do inside the destructor is use the thread pool to perform the removal of the item from the dictionary. You would still need to mark the wrapper instance as no longer valid, so that if a call is made to any of its public methods between the finalizer running and the thread pool removing it, you could detect this and reject the call.

So the reason you DON'T want to use locking in a destructor is due to the fact that the destructor might be called by a FinalizerWorker in a sperate thread while stopping execution on all threads.
Thus, if one thread is in the middle of a ConcurrencyDicitonary operation when the FinalizerWorker is kicked off you might deadlock if the destructor tries to lock the ConcurrencyDictionary (this can be a very difficult to reproduce deadlock).
A spin lock wont help you because if ANY currently executing thread has the ConcurrencyDictionary locked or the Spinner variable locked it WILL NOT release it until the FinalizerWorker completes, which it wont because it will spin/lock forever.
You'r main options here is to implement the IDisposable interface with a SuppressFinalize(this) call, since your object will suppress the Finalizer worker no deadlock can occure and ConcurrencyDictionary operations ARE SAFE !
Thus if you pre-empt Finalizer using object.Dispose() you should be safe use ConcurrencyDictionary, but otherwise DO NOT use any types of locks in your Finalizer Dispose(false) call or you will deadlock at some point.
// Design pattern for a base class.
public class Base: IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
//Disposing outside the FinalizerWorker (SAFE)
if (disposing)
m_pDictionary.TryRemove(this);
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~Base()
{
// Simply call Dispose(false).
Dispose (false);
}

The answers on here are leading you astray. Using locks in a destructor/finalizer is discouraged because it can easily lead to deadlocks, especially when implemented "manually" instead of using a concurrent collection, but sometimes it is necessary. Even on "stop the world" GC implementations finalizers run on a separate finalizer thread that chugs along concurrently with your application.
First thing is first though - it is VERY RARE that what you are suggesting is the ideal way of implementing your desired functionality, to the point where I am quite confident it isn't. To start, WeakReferences are not suitable for use in caching because they get collected far more often than just when "memory is needed". A proper cache implementation monitors memory levels with strong references and releases them as needed when memory usage is too high.
Even in implementations like a WeakValueDictionary where you don't want the collection holding onto the value if it can be collected, the implementation still doesn't receive object collection notifications. Instead you just remove the entry whenever you stumble upon one that was collected, or you scan the entire collection for dead entries every X operations, or every Y seconds, etc.
That said, if you do run into a situation where you NEED to do something when an object is collected, you can use concurrent collections just fine.
Assuming you don't do anything silly, queuing up an ID in a notification queue or removing an item from a concurrent dictionary is safe because those operations are fast and block for only a very short period of time and your application is not blocked while your finalizers run.
It's something you should avoid as much as possible, but sometimes it's the best and only way to implement something. Just make sure that the lock is fast and used as minimally as possible, and not part of any multi-level locking schemes that are easy to accidentally get wrong and deadlock.

Related

C# dispose unmanaged object stored in managed collection [duplicate]

I know from reading Microsoft documentation that the "primary" use of the IDisposable interface is to clean up unmanaged resources.
To me, "unmanaged" means things like database connections, sockets, window handles, etc. But, I've seen code where the Dispose() method is implemented to free managed resources, which seems redundant to me, since the garbage collector should take care of that for you.
For example:
public class MyCollection : IDisposable
{
private List<String> _theList = new List<String>();
private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();
// Die, clear it up! (free unmanaged resources)
public void Dispose()
{
_theList.clear();
_theDict.clear();
_theList = null;
_theDict = null;
}
}
My question is, does this make the garbage collector free memory used by MyCollection any faster than it normally would?
Edit: So far people have posted some good examples of using IDisposable to clean up unmanaged resources such as database connections and bitmaps. But suppose that _theList in the above code contained a million strings, and you wanted to free that memory now, rather than waiting for the garbage collector. Would the above code accomplish that?
The point of Dispose is to free unmanaged resources. It needs to be done at some point, otherwise they will never be cleaned up. The garbage collector doesn't know how to call DeleteHandle() on a variable of type IntPtr, it doesn't know whether or not it needs to call DeleteHandle().
Note: What is an unmanaged resource? If you found it in the Microsoft .NET Framework: it's managed. If you went poking around MSDN yourself, it's unmanaged. Anything you've used P/Invoke calls to get outside of the nice comfy world of everything available to you in the .NET Framework is unmanaged – and you're now responsible for cleaning it up.
The object that you've created needs to expose some method, that the outside world can call, in order to clean up unmanaged resources. The method can be named whatever you like:
public void Cleanup()
or
public void Shutdown()
But instead there is a standardized name for this method:
public void Dispose()
There was even an interface created, IDisposable, that has just that one method:
public interface IDisposable
{
void Dispose()
}
So you make your object expose the IDisposable interface, and that way you promise that you've written that single method to clean up your unmanaged resources:
public void Dispose()
{
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}
And you're done. Except you can do better.
What if your object has allocated a 250MB System.Drawing.Bitmap (i.e. the .NET managed Bitmap class) as some sort of frame buffer? Sure, this is a managed .NET object, and the garbage collector will free it. But do you really want to leave 250MB of memory just sitting there – waiting for the garbage collector to eventually come along and free it? What if there's an open database connection? Surely we don't want that connection sitting open, waiting for the GC to finalize the object.
If the user has called Dispose() (meaning they no longer plan to use the object) why not get rid of those wasteful bitmaps and database connections?
So now we will:
get rid of unmanaged resources (because we have to), and
get rid of managed resources (because we want to be helpful)
So let's update our Dispose() method to get rid of those managed objects:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
And all is good, except you can do better!
What if the person forgot to call Dispose() on your object? Then they would leak some unmanaged resources!
Note: They won't leak managed resources, because eventually the garbage collector is going to run, on a background thread, and free the memory associated with any unused objects. This will include your object, and any managed objects you use (e.g. the Bitmap and the DbConnection).
If the person forgot to call Dispose(), we can still save their bacon! We still have a way to call it for them: when the garbage collector finally gets around to freeing (i.e. finalizing) our object.
Note: The garbage collector will eventually free all managed objects.
When it does, it calls the Finalize
method on the object. The GC doesn't know, or
care, about your Dispose method.
That was just a name we chose for
a method we call when we want to get
rid of unmanaged stuff.
The destruction of our object by the Garbage collector is the perfect time to free those pesky unmanaged resources. We do this by overriding the Finalize() method.
Note: In C#, you don't explicitly override the Finalize() method.
You write a method that looks like a C++ destructor, and the
compiler takes that to be your implementation of the Finalize() method:
~MyObject()
{
//we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
Dispose(); //<--Warning: subtle bug! Keep reading!
}
But there's a bug in that code. You see, the garbage collector runs on a background thread; you don't know the order in which two objects are destroyed. It is entirely possible that in your Dispose() code, the managed object you're trying to get rid of (because you wanted to be helpful) is no longer there:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
this.frameBufferImage = null;
}
}
So what you need is a way for Finalize() to tell Dispose() that it should not touch any managed resources (because they might not be there anymore), while still freeing unmanaged resources.
The standard pattern to do this is to have Finalize() and Dispose() both call a third(!) method; where you pass a Boolean saying if you're calling it from Dispose() (as opposed to Finalize()), meaning it's safe to free managed resources.
This internal method could be given some arbitrary name like "CoreDispose", or "MyInternalDispose", but is tradition to call it Dispose(Boolean):
protected void Dispose(Boolean disposing)
But a more helpful parameter name might be:
protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too, but only if I'm being called from Dispose
//(If I'm being called from Finalize then the objects might not exist
//anymore
if (itIsSafeToAlsoFreeManagedObjects)
{
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
}
And you change your implementation of the IDisposable.Dispose() method to:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
}
and your finalizer to:
~MyObject()
{
Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}
Note: If your object descends from an object that implements Dispose, then don't forget to call their base Dispose method when you override Dispose:
public override void Dispose()
{
try
{
Dispose(true); //true: safe to free managed resources
}
finally
{
base.Dispose();
}
}
And all is good, except you can do better!
If the user calls Dispose() on your object, then everything has been cleaned up. Later on, when the garbage collector comes along and calls Finalize, it will then call Dispose again.
Not only is this wasteful, but if your object has junk references to objects you already disposed of from the last call to Dispose(), you'll try to dispose them again!
You'll notice in my code I was careful to remove references to objects that I've disposed, so I don't try to call Dispose on a junk object reference. But that didn't stop a subtle bug from creeping in.
When the user calls Dispose(): the handle CursorFileBitmapIconServiceHandle is destroyed. Later when the garbage collector runs, it will try to destroy the same handle again.
protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy
...
}
The way you fix this is tell the garbage collector that it doesn't need to bother finalizing the object – its resources have already been cleaned up, and no more work is needed. You do this by calling GC.SuppressFinalize() in the Dispose() method:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}
Now that the user has called Dispose(), we have:
freed unmanaged resources
freed managed resources
There's no point in the GC running the finalizer – everything's taken care of.
Couldn't I use Finalize to cleanup unmanaged resources?
The documentation for Object.Finalize says:
The Finalize method is used to perform cleanup operations on unmanaged resources held by the current object before the object is destroyed.
But the MSDN documentation also says, for IDisposable.Dispose:
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
So which is it? Which one is the place for me to cleanup unmanaged resources? The answer is:
It's your choice! But choose Dispose.
You certainly could place your unmanaged cleanup in the finalizer:
~MyObject()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//A C# destructor automatically calls the destructor of its base class.
}
The problem with that is you have no idea when the garbage collector will get around to finalizing your object. Your un-managed, un-needed, un-used native resources will stick around until the garbage collector eventually runs. Then it will call your finalizer method; cleaning up unmanaged resources. The documentation of Object.Finalize points this out:
The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a IDisposable.Dispose implementation.
This is the virtue of using Dispose to cleanup unmanaged resources; you get to know, and control, when unmanaged resource are cleaned up. Their destruction is "deterministic".
To answer your original question: Why not release memory now, rather than for when the GC decides to do it? I have a facial recognition software that needs to get rid of 530 MB of internal images now, since they're no longer needed. When we don't: the machine grinds to a swapping halt.
Bonus Reading
For anyone who likes the style of this answer (explaining the why, so the how becomes obvious), I suggest you read Chapter One of Don Box's Essential COM:
Direct link: Chapter 1 sample by Pearson Publishing
magnet: 84bf0b960936d677190a2be355858e80ef7542c0
In 35 pages he explains the problems of using binary objects, and invents COM before your eyes. Once you realize the why of COM, the remaining 300 pages are obvious, and just detail Microsoft's implementation.
I think every programmer who has ever dealt with objects or COM should, at the very least, read the first chapter. It is the best explanation of anything ever.
Extra Bonus Reading
When everything you know is wrong archiveby Eric Lippert
It is therefore very difficult indeed to write a correct finalizer,
and the best advice I can give you is to not try.
IDisposable is often used to exploit the using statement and take advantage of an easy way to do deterministic cleanup of managed objects.
public class LoggingContext : IDisposable {
public Finicky(string name) {
Log.Write("Entering Log Context {0}", name);
Log.Indent();
}
public void Dispose() {
Log.Outdent();
}
public static void Main() {
Log.Write("Some initial stuff.");
try {
using(new LoggingContext()) {
Log.Write("Some stuff inside the context.");
throw new Exception();
}
} catch {
Log.Write("Man, that was a heavy exception caught from inside a child logging context!");
} finally {
Log.Write("Some final stuff.");
}
}
}
The purpose of the Dispose pattern is to provide a mechanism to clean up both managed and unmanaged resources and when that occurs depends on how the Dispose method is being called. In your example, the use of Dispose is not actually doing anything related to dispose, since clearing a list has no impact on that collection being disposed. Likewise, the calls to set the variables to null also have no impact on the GC.
You can take a look at this article for more details on how to implement the Dispose pattern, but it basically looks like this:
public class SimpleCleanup : IDisposable
{
// some fields that require cleanup
private SafeHandle handle;
private bool disposed = false; // to detect redundant calls
public SimpleCleanup()
{
this.handle = /*...*/;
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
if (handle != null)
{
handle.Dispose();
}
}
// Dispose unmanaged managed resources.
disposed = true;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
The method that is the most important here is the Dispose(bool), which actually runs under two different circumstances:
disposing == true: the method has been called directly or indirectly by a user's code. Managed and unmanaged resources can be disposed.
disposing == false: the method has been called by the runtime from inside the finalizer, and you should not reference other objects. Only unmanaged resources can be disposed.
The problem with simply letting the GC take care of doing the cleanup is that you have no real control over when the GC will run a collection cycle (you can call GC.Collect(), but you really shouldn't) so resources may stay around longer than needed. Remember, calling Dispose() doesn't actually cause a collection cycle or in any way cause the GC to collect/free the object; it simply provides the means to more deterministicly cleanup the resources used and tell the GC that this cleanup has already been performed.
The whole point of IDisposable and the dispose pattern isn't about immediately freeing memory. The only time a call to Dispose will actually even have a chance of immediately freeing memory is when it is handling the disposing == false scenario and manipulating unmanaged resources. For managed code, the memory won't actually be reclaimed until the GC runs a collection cycle, which you really have no control over (other than calling GC.Collect(), which I've already mentioned is not a good idea).
Your scenario isn't really valid since strings in .NET don't use any unamanged resources and don't implement IDisposable, there is no way to force them to be "cleaned up."
There should be no further calls to an object's methods after Dispose has been called on it (although an object should tolerate further calls to Dispose). Therefore the example in the question is silly. If Dispose is called, then the object itself can be discarded. So the user should just discard all references to that whole object (set them to null) and all the related objects internal to it will automatically get cleaned up.
As for the general question about managed/unmanaged and the discussion in other answers, I think any answer to this question has to start with a definition of an unmanaged resource.
What it boils down to is that there is a function you can call to put the system into a state, and there's another function you can call to bring it back out of that state. Now, in the typical example, the first one might be a function that returns a file handle, and the second one might be a call to CloseHandle.
But - and this is the key - they could be any matching pair of functions. One builds up a state, the other tears it down. If the state has been built but not torn down yet, then an instance of the resource exists. You have to arrange for the teardown to happen at the right time - the resource is not managed by the CLR. The only automatically managed resource type is memory. There are two kinds: the GC, and the stack. Value types are managed by the stack (or by hitching a ride inside reference types), and reference types are managed by the GC.
These functions may cause state changes that can be freely interleaved, or may need to be perfectly nested. The state changes may be threadsafe, or they might not.
Look at the example in Justice's question. Changes to the Log file's indentation must be perfectly nested, or it all goes wrong. Also they are unlikely to be threadsafe.
It is possible to hitch a ride with the garbage collector to get your unmanaged resources cleaned up. But only if the state change functions are threadsafe and two states can have lifetimes that overlap in any way. So Justice's example of a resource must NOT have a finalizer! It just wouldn't help anyone.
For those kinds of resources, you can just implement IDisposable, without a finalizer. The finalizer is absolutely optional - it has to be. This is glossed over or not even mentioned in many books.
You then have to use the using statement to have any chance of ensuring that Dispose is called. This is essentially like hitching a ride with the stack (so as finalizer is to the GC, using is to the stack).
The missing part is that you have to manually write Dispose and make it call onto your fields and your base class. C++/CLI programmers don't have to do that. The compiler writes it for them in most cases.
There is an alternative, which I prefer for states that nest perfectly and are not threadsafe (apart from anything else, avoiding IDisposable spares you the problem of having an argument with someone who can't resist adding a finalizer to every class that implements IDisposable).
Instead of writing a class, you write a function. The function accepts a delegate to call back to:
public static void Indented(this Log log, Action action)
{
log.Indent();
try
{
action();
}
finally
{
log.Outdent();
}
}
And then a simple example would be:
Log.Write("Message at the top");
Log.Indented(() =>
{
Log.Write("And this is indented");
Log.Indented(() =>
{
Log.Write("This is even more indented");
});
});
Log.Write("Back at the outermost level again");
The lambda being passed in serves as a code block, so it's like you make your own control structure to serve the same purpose as using, except that you no longer have any danger of the caller abusing it. There's no way they can fail to clean up the resource.
This technique is less useful if the resource is the kind that may have overlapping lifetimes, because then you want to be able to build resource A, then resource B, then kill resource A and then later kill resource B. You can't do that if you've forced the user to perfectly nest like this. But then you need to use IDisposable (but still without a finalizer, unless you have implemented threadsafety, which isn't free).
Scenarios I make use of IDisposable: clean up unmanaged resources, unsubscribe for events, close connections
The idiom I use for implementing IDisposable (not threadsafe):
class MyClass : IDisposable {
// ...
#region IDisposable Members and Helpers
private bool disposed = false;
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) {
if (!this.disposed) {
if (disposing) {
// cleanup code goes here
}
disposed = true;
}
}
~MyClass() {
Dispose(false);
}
#endregion
}
Yep, that code is completely redundant and unnecessary and it doesn't make the garbage collector do anything it wouldn't otherwise do (once an instance of MyCollection goes out of scope, that is.) Especially the .Clear() calls.
Answer to your edit: Sort of. If I do this:
public void WasteMemory()
{
var instance = new MyCollection(); // this one has no Dispose() method
instance.FillItWithAMillionStrings();
}
// 1 million strings are in memory, but marked for reclamation by the GC
It's functionally identical to this for purposes of memory management:
public void WasteMemory()
{
var instance = new MyCollection(); // this one has your Dispose()
instance.FillItWithAMillionStrings();
instance.Dispose();
}
// 1 million strings are in memory, but marked for reclamation by the GC
If you really really really need to free the memory this very instant, call GC.Collect(). There's no reason to do this here, though. The memory will be freed when it's needed.
If MyCollection is going to be garbage collected anyway, then you shouldn't need to dispose it. Doing so will just churn the CPU more than necessary, and may even invalidate some pre-calculated analysis that the garbage collector has already performed.
I use IDisposable to do things like ensure threads are disposed correctly, along with unmanaged resources.
EDIT In response to Scott's comment:
The only time the GC performance metrics are affected is when a call the [sic] GC.Collect() is made"
Conceptually, the GC maintains a view of the object reference graph, and all references to it from the stack frames of threads. This heap can be quite large and span many pages of memory. As an optimisation, the GC caches its analysis of pages that are unlikely to change very often to avoid rescanning the page unnecessarily. The GC receives notification from the kernel when data in a page changes, so it knows that the page is dirty and requires a rescan. If the collection is in Gen0 then it's likely that other things in the page are changing too, but this is less likely in Gen1 and Gen2. Anecdotally, these hooks were not available in Mac OS X for the team who ported the GC to Mac in order to get the Silverlight plug-in working on that platform.
Another point against unnecessary disposal of resources: imagine a situation where a process is unloading. Imagine also that the process has been running for some time. Chances are that many of that process's memory pages have been swapped to disk. At the very least they're no longer in L1 or L2 cache. In such a situation there is no point for an application that's unloading to swap all those data and code pages back into memory to 'release' resources that are going to be released by the operating system anyway when the process terminates. This applies to managed and even certain unmanaged resources. Only resources that keep non-background threads alive must be disposed, otherwise the process will remain alive.
Now, during normal execution there are ephemeral resources that must be cleaned up correctly (as #fezmonkey points out database connections, sockets, window handles) to avoid unmanaged memory leaks. These are the kinds of things that have to be disposed. If you create some class that owns a thread (and by owns I mean that it created it and therefore is responsible for ensuring it stops, at least by my coding style), then that class most likely must implement IDisposable and tear down the thread during Dispose.
The .NET framework uses the IDisposable interface as a signal, even warning, to developers that the this class must be disposed. I can't think of any types in the framework that implement IDisposable (excluding explicit interface implementations) where disposal is optional.
I won't repeat the usual stuff about Using or freeing un-managed resources, that has all been covered. But I would like to point out what seems a common misconception.
Given the following code
Public Class LargeStuff
Implements IDisposable
Private _Large as string()
'Some strange code that means _Large now contains several million long strings.
Public Sub Dispose() Implements IDisposable.Dispose
_Large=Nothing
End Sub
I realise that the Disposable implementation does not follow current guidelines, but hopefully you all get the idea.
Now, when Dispose is called, how much memory gets freed?
Answer: None.
Calling Dispose can release unmanaged resources, it CANNOT reclaim managed memory, only the GC can do that. Thats not to say that the above isn't a good idea, following the above pattern is still a good idea in fact. Once Dispose has been run, there is nothing stopping the GC re-claiming the memory that was being used by _Large, even though the instance of LargeStuff may still be in scope. The strings in _Large may also be in gen 0 but the instance of LargeStuff might be gen 2, so again, memory would be re-claimed sooner.
There is no point in adding a finaliser to call the Dispose method shown above though. That will just DELAY the re-claiming of memory to allow the finaliser to run.
In the example you posted, it still doesn't "free the memory now". All memory is garbage collected, but it may allow the memory to be collected in an earlier generation. You'd have to run some tests to be sure.
The Framework Design Guidelines are guidelines, and not rules. They tell you what the interface is primarily for, when to use it, how to use it, and when not to use it.
I once read code that was a simple RollBack() on failure utilizing IDisposable. The MiniTx class below would check a flag on Dispose() and if the Commit call never happened it would then call Rollback on itself. It added a layer of indirection making the calling code a lot easier to understand and maintain. The result looked something like:
using( MiniTx tx = new MiniTx() )
{
// code that might not work.
tx.Commit();
}
I've also seen timing / logging code do the same thing. In this case the Dispose() method stopped the timer and logged that the block had exited.
using( LogTimer log = new LogTimer("MyCategory", "Some message") )
{
// code to time...
}
So here are a couple of concrete examples that don't do any unmanaged resource cleanup, but do successfully used IDisposable to create cleaner code.
If you want to delete right now, use unmanaged memory.
See:
Marshal.AllocHGlobal
Marshal.FreeHGlobal
Marshal.DestroyStructure
If anything, I'd expect the code to be less efficient than when leaving it out.
Calling the Clear() methods are unnecessary, and the GC probably wouldn't do that if the Dispose didn't do it...
Apart from its primary use as a way to control the lifetime of system resources (completely covered by the awesome answer of Ian, kudos!), the IDisposable/using combo can also be used to scope the state change of (critical) global resources: the console, the threads, the process, any global object like an application instance.
I've written an article about this pattern: http://pragmateek.com/c-scope-your-global-state-changes-with-idisposable-and-the-using-statement/
It illustrates how you can protect some often used global state in a reusable and readable manner: console colors, current thread culture, Excel application object properties...
I see a lot of answers have shifted to talk about using IDisposable for both managed and unmanaged resources. I'd suggest this article as one of the best explanations that I've found for how IDisposable should actually be used.
https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About
For the actual question; should you use IDisposable to clean up managed objects that are taking up a lot of memory the short answer would be no. The reason is that once your object that is holding the memory goes out of scope it is ready for collection. At that point any referenced child objects are also out of scope and will get collected.
The only real exception to this would be if you have a lot of memory tied up in managed objects and you've blocked that thread waiting for some operation to complete. If those objects where not going to be needed after that call completed then setting those references to null might allow the garbage collector to collect them sooner. But that scenario would represent bad code that needed to be refactored - not a use case of IDisposable.
IDisposable is good for unsubscribing from events.
Your given code sample is not a good example for IDisposable usage. Dictionary clearing normally shouldn't go to the Dispose method. Dictionary items will be cleared and disposed when it goes out of scope. IDisposable implementation is required to free some memory/handlers that will not release/free even after they out of scope.
The following example shows a good example for IDisposable pattern with some code and comments.
public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;
// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
// Note disposing has been done.
disposed = true;
}
}
// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}
There are things that the Dispose() operation does in the example code that might have an effect that would not occur due to a normal GC of the MyCollection object.
If the objects referenced by _theList or _theDict are referred to by other objects, then that List<> or Dictionary<> object will not be subject to collection but will suddenly have no contents. If there were no Dispose() operation as in the example, those collections would still contain their contents.
Of course, if this were the situation I would call it a broken design - I'm just pointing out (pedantically, I suppose) that the Dispose() operation might not be completely redundant, depending on whether there are other uses of the List<> or Dictionary<> that are not shown in the fragment.
One problem with most discussions of "unmanaged resources" is that they don't really define the term, but seem to imply that it has something to do with unmanaged code. While it is true that many types of unmanaged resources do interface with unmanaged code, thinking of unmanaged resources in such terms isn't helpful.
Instead, one should recognize what all managed resources have in common: they all entail an object asking some outside 'thing' to do something on its behalf, to the detriment of some other 'things', and the other entity agreeing to do so until further notice. If the object were to be abandoned and vanish without a trace, nothing would ever tell that outside 'thing' that it no longer needed to alter its behavior on behalf of the object that no longer existed; consequently, the 'thing's usefulness would be permanently diminished.
An unmanaged resource, then, represents an agreement by some outside 'thing' to alter its behavior on behalf of an object, which would useless impair the usefulness of that outside 'thing' if the object were abandoned and ceased to exist. A managed resource is an object which is the beneficiary of such an agreement, but which has signed up to receive notification if it is abandoned, and which will use such notification to put its affairs in order before it is destroyed.
First of definition. For me unmanaged resource means some class, which implements IDisposable interface or something created with usage of calls to dll. GC doesn't know how to deal with such objects. If class has for example only value types, then I don't consider this class as class with unmanaged resources.
For my code I follow next practices:
If created by me class uses some unmanaged resources then it means that I should also implement IDisposable interface in order to clean memory.
Clean objects as soon as I finished usage of it.
In my dispose method I iterate over all IDisposable members of class and call Dispose.
In my Dispose method call GC.SuppressFinalize(this) in order to notify garbage collector that my object was already cleaned up. I do it because calling of GC is expensive operation.
As additional precaution I try to make possible calling of Dispose() multiple times.
Sometime I add private member _disposed and check in method calls did object was cleaned up. And if it was cleaned up then generate ObjectDisposedException
Following template demonstrates what I described in words as sample of code:
public class SomeClass : IDisposable
{
/// <summary>
/// As usually I don't care was object disposed or not
/// </summary>
public void SomeMethod()
{
if (_disposed)
throw new ObjectDisposedException("SomeClass instance been disposed");
}
public void Dispose()
{
Dispose(true);
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)//we are in the first call
{
}
_disposed = true;
}
}
The most justifiable use case for disposal of managed resources, is preparation for the GC to reclaim resources that would otherwise never be collected.
A prime example is circular references.
Whilst it's best practice to use patterns that avoid circular references, if you do end up with (for example) a 'child' object that has a reference back to its 'parent', this can stop GC collection of the parent if you just abandon the reference and rely on GC - plus if you have implemented a finalizer, it'll never be called.
The only way round this is to manually break the circular references by setting the Parent references to null on the children.
Implementing IDisposable on parent and children is the best way to do this. When Dispose is called on the Parent, call Dispose on all Children, and in the child Dispose method, set the Parent references to null.
I think people are conflating the PATTERN of IDisposable with the primary purpose of IDisposable which was meant to help clean up unmanaged resources. We all know this. Some think the pattern has some sort of magical powers that clears memory and frees resources. The PATTERN does NOT do this. But the usage of the pattern with the methods that are implemented DO clear memory and free resources.
The pattern is simply a built in try{} finally{} block. Nothing more. Nothing less. So what does that mean? You can create a block of code that lets you do something at the end without having to do extra code for it. It provides a CUSTOM block you can use to segment code and scope.
My example:
//My way
using (var _ = new Metric("My Test"))
{
DoSomething(); //You now know all work in your block is being timed.
}
//MS mockup from memory
var sw = new Stopwatch();
sw.Start();
DoSomething(); //something fails? I never get the elapsed time this way
sw.Stop();
Metric class
public class Metric : IDisposable
{
private string _identifier;
private DateTime _start;
public Metric(string identifier)
{
_identifier = identifier;
_start = DateTime.Now;
}
public void Dispose()
{
Console.WriteLine(_identifier + " - " + (DateTime.Now - _start).TotalMilliseconds)
}
}

Calling dispose within list.removeAll

I'm pretty new to C# programming, and the concept of the GC, and its realtions to IDisposable is still a bit vague. What does calling Dispose mean in terms of the garbage collection?
Specifically i wonder if the following code may fail occationally, depending on when the garbage collection kicks in. (I have not been able to make it crash during my tests).
//List<TestClass2> tc2List;
//TestClass2 invokes a thread. It implements IDisposable.
//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)
tc2List.RemoveAll(t =>
{
if (String.Compare(t.Name, "Orange") == 0)
{
t.Dispose(); //May take up to 100 msek
return true;
}
return false;
});
Your code works, but it's bad style. Predicates should not have side effects. So you should first dispose the elements, and then remove them.
Predicate<T> filter = t => t.Name == "Orange";
foreach(var t in tc2List.Where(filter))
t.Dispose();
tc2List.RemoveAll(filter);
i wonder if the following code may fail occationally, depending on when the garbage collection kicks in
No, it won't fail
//Its Dispose() sets a stop-condition for the thread,
//and joins the thread, awaiting it to stop. (may take 100 msek)
That is a slightly a-typical use of Dispose() but not wrong. A more efficient approach would use a different Stop() so that you can stop all threads at once. Or call Dispose() from Parallel.ForEach(). But whatever method you choose, it is not hindering, nor is it being hindered by, the GC.
Do you have finalize method in you TestClass2?
Dispose main properties
This has to be implemented in classes implementing IDispose interface.
Its the right place for freeing-up unmanaged resources like file, handles, and connections etc.
Dispose() method is called explicitely in the code itself.
Dispose() method is automatically called (for objects which implement IDispose), when used in a "using"
Refer to link.
What does calling Dispose mean in terms of the garbage collection?
Calling dispose, means you are forcibly cleaning up things (literally the memory) using your implementation of the Dispose method. Note : (Some of the framework classes do call your implementation of Dispose for you. System.Windows.Forms.Form for example)
Garbage collection on the contrast is a feature of the .NET runtime that will clean up things for you automatically. Automatically i mean, because its up to the memory pressure and other factors that is taken care by the runtime.
A simple strategy i would recommend. Do Dispose() if you think that the memory would stay longer than needed and would impact the application. Else leave it to the runtime, it will automatically cleans up (i.e finalizes) the objects when they go out of scope. The GC has its own algorithm on how to do cleanup, but you can to a greater extent rely on it.
The next question
Specifically i wonder if the following code may fail occasionally, depending on when the garbage collection kicks in
I guess no. Failure of the code due to GC kicking in, depends on how you write the finalizer of TestClass2. Definitely your call t.Dispose() wont clash with the GC.

For Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose?

Regarding the Microsoft built classes that inherit IDisposable, do I explicitly have to call Dispose to prevent memory leaks?
I understand that it is best practice to call Dispose (or better yet use a using block), however when programming, typically I don't always immediately realise that a class inherits from IDisposable.
I also understand that Microsoft implementation of IDisposable is a bit borked, which is why they created the article explaining the correct usage of IDisposable.
Long story short, in which instances is it okay to forget to call Dispose?
There are a couple of issues in the primary question
Do I explicitly have to call Dispose to prevent memory leaks?
Calling Dispose on any type which implements IDisposable is highly recomended and may even be a fundamental part of the types contract. There is almost no good reason to not call Dispose when you are done with the object. An IDisposable object is meant to be disposed.
But will failing to call Dispose create a memory leak? Possibly. It's very dependent on what exactly that object does in it's Dispose method. Many free memory, some unhook from events, others free handles, etc ... It may not leak memory but it will almost certainly have a negative effect on your program
In which instances is it okay to forget to call Dispose?
I'd start with none. The vast majority of objects out there implement IDisposable for good reason. Failing to call Dispose will hurt your program.
It depends on two things:
What happens in the Dispose method
Does the finalizer call Dispose
Dispose functionlity
Dispose can do several type of actions, like closing a handle to a resource (like file stream), change the class state and release other components the class itself uses.
In case of resource being released (like file) there's a functionality difference between calling it explicitly and waiting for it to be called during garbage collection (assuming the finalizer calls dispose).
In case there's no state change and only components are released there'll be no memory leak since the object will be freed by the GC later.
Finalizer
In most cases, disposable types call the Dispose method from the finalizer. If this is the case, and assuming the context in which the dispose is called doesn't matter, then there's a high chance that you'll notice no difference if the object will not be disposed explicitly. But, if the Dispose is not called from the finalizer then your code will behave differently.
Bottom line - in most cases, it's better to dispose the object explicitly when you're done with it.
A simple example to where it's better to call Dispose explicitly: Assuming you're using a FileStream to write some content and enable no sharing, then the file is locked by the process until the GC will get the object. The file may also not flush all the content to the file so if the process crashes in some point after the write was over it's not guaranteed that it will actually be saved.
It can be safe to not call Dispose, but the problem is knowing when this is the case.
A good 95% of IEnumerator<T> implementations have a Dispose that's safe to ignore, but the 5% is not just 5% that'll cause a bug, but 5% that'll cause a nasty hard to trace bug. More to the point, code that gets passed an IEnumerator<T> will see both the 95% and the 5% and won't be able to dynamically tell them apart (it's possible to implement the non-generic IEnumerable without implementing IDisposable, and how well that turned out can be guessed at by MS deciding to make IEnumerator<T> inherit from IDisposable!).
Of the rest, maybe there's 3 or 4% of the time it's safe. For now. You don't know which 3% without looking at the code, and even then the contract says you have to call it, so the developer can depend on you doing so if they release a new version where it is important.
In summary, always call Dispose(). (I can think of an exception, but it's frankly too weird to even go into the details of, and it's still safe to call it in that case, just not vital).
On the question of implementing IDisposable yourself, avoid the pattern in that accursed document.
I consider that pattern an anti-pattern. It is a good pattern for implementing both IDisposable.Dispose and a finaliser in a class that holds both managed and unmanaged resources. However holding both managed IDisposable and unmanaged resources is a bad idea in the first place.
Instead:
If you have an unmanaged resource, then don't have any unmanaged resources that implement IDisposable. Now the Dispose(true) and Dispose(false) code paths are the same, so really they can become:
public class HasUnmanaged : IDisposable
{
IntPtr unmanagedGoo;
private void CleanUp()
{
if(unmanagedGoo != IntPtr.Zero)
{
SomeReleasingMethod(unmanagedGoo);
unmanagedGoo = IntPtr.Zero;
}
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanaged()
{
CleanUp();
}
}
If you have managed resources that need to be disposed, then just do that:
public class HasUnmanaged : IDisposable
{
IDisposable managedGoo;
public void Dispose()
{
if(managedGoo != null)
managedGoo.Dispose();
}
}
There, no cryptic "disposing" bool (how can something be called Dispose and take false for something called disposing?) No worrying about finalisers for the 99.99% of the time you won't need them (the second pattern is way more common than the first). All good.
Really need something that has both a managed and an unmanaged resource? No, you don't really, wrap the unmanaged resource in a class of your own that works as a handle to it, and then that handle fits the first pattern above and the main class fits the second.
Only implement the CA10634 pattern when you're forced to because you inherited from a class that did so. Thankfully, most people aren't creating new ones like that any more.
It is never OK to forget to call Dispose (or, as you say, better yet use using).
I guess if the goal of your program is to cause unmanaged resource leaks. Then maybe it would be OK.
The implementation of IDisposable indicates that a class uses un-managed resources. You should always call Dispose() (or use a using block when possible) when you're sure you're done with the class. Otherwise you are unnecessarily keeping un-managed resources allocated.
In other words, never forget to call Dispose().
Yes, always call dispose. Either explicitly or implicitly (via using). Take, for example, the Timer class. If you do not explicitly stop a timer, and do not dispose it, then it will keep firing until the garbage collector gets around to collecting it. This could actually cause crashes or unexpected behavior.
It's always best to make sure Dispose is called as soon as you are done with it.
Microsoft (probably not officially) says it is ok to not call Dispose in some cases.
Stephen Toub from Microsoft writes (about calling Dispose on Task):
In short, as is typically the case in .NET, dispose aggressively if
it's easy and correct to do based on the structure of your code. If
you start having to do strange gyrations in order to Dispose (or in
the case of Tasks, use additional synchronization to ensure it's safe
to dispose, since Dispose may only be used once a task has completed),
it's likely better to rely on finalization to take care of things. In
the end, it's best to measure, measure, measure to see if you actually
have a problem before you go out of your way to make the code less
sightly in order to implement clean-up functionality.
[bold emphasize is mine]
Another case is base streams
var inner = new FileStrem(...);
var outer = new StreamReader(inner, Encoding.GetEncoding(1252));
...
outer.Dispose();
inner.Dispose(); -- this will trigger a FxCop performance warning about calling Dispose twice.
(I have turned off this rule)

Which objects can I use in a finalizer method?

I have a class that should delete some file when disposed or finalized. Inside finalizers I can't use other objects because they could have been garbage-collected already.
Am I missing some point regarding finalizers and strings could be used?
UPD: Something like that:
public class TempFileStream : FileStream
{
private string _filename;
public TempFileStream(string filename)
:base(filename, FileMode.Open, FileAccess.Read, FileShare.Read)
{
_filename = filename;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_filename == null) return;
try
{
File.Delete(_filename); // <-- oops! _filename could be gc-ed already
_filename = null;
}
catch (Exception e)
{
...
}
}
}
Yes, you can most certainly use strings from within a finalizer, and many other object types.
For the definitive source of all this, I would go pick up the book CLR via C#, 3rd edition, written by Jeffrey Richter. In chapter 21 this is all described in detail.
Anyway, here's what is really happening...
During garbage collection, any objects that have a finalizer that still wants to be called are placed on a special list, called the freachable list.
This list is considered a root, just as static variables and live local variables are. Therefore, any objects those objects refer to, and so on recursively is removed from the garbage collection cycle this time. They will survive the current garbage collection cycle as though they weren't eligible to collect to begin with.
Note that this includes strings, which was your question, but it also involves all other object types
Then, at some later point in time, the finalizer thread picks up the object from that list, and runs the finalizer on those objects, and then takes those objects off that list.
Then, the next time garbage collection runs, it finds the same objects once more, but this time the finalizer no longer wants to run, it has already been executed, and so the objects are collected as normal.
Let me illustrate with an example before I tell you what doesn't work.
Let's say you have objects A through Z, and each object references the next one, so you have object A referencing object B, B references C, C references D, and so on until Z.
Some of these objects implement finalizers, and they all implement IDisposable. Let's assume that A does not implement a finalizer but B does, and then some of the rest does as well, it's not important for this example which does beyond A and B.
Your program holds onto a reference to A, and only A.
In an ordinary, and correct, usage pattern you would dispose of A, which would dispose of B, which would dispose of C, etc. but you have a bug, so this doesn't happen. At some point, all of these objects are eligible for collection.
At this point GC will find all of these objects, but then notice that B has a finalizer, and it has not yet run. GC will therefore put B on the freachable list, and recursively take C, D, E, etc. up to Z, off of the GC list, because since B suddenly became in- eligible for collection, so does the rest. Note that some of these objects are also placed on the freachable list themselves, because they have finalizers on their own, but all the objects they refer to will survive GC.
A, however, is collected.
Let me make the above paragraph clear. At this point, A has been collected, but B, C, D, etc. up to Z are still alive as though nothing has happened. Though your code no longer has a reference to any of them, the freachable list has.
Then, the finalizer thread runs, and finalizes all of the objects in the freachable list, and takes the objects off of the list.
The next time GC is run, those objects are now collected.
So that certainly works, so what is the big bruaha about?
The problem is with the finalizer thread. This thread makes no assumptions about the order in which it should finalize those objects. It doesn't do this because in many cases it would be impossible for it to do so.
As I said above, in an ordinary world you would call dispose on A, which disposes B, which disposes C, etc. If one of these objects is a stream, the object referencing the stream might, in its call to Dispose, say "I'll just go ahead and flush my buffers before disposing the stream." This is perfectly legal and lots of existing code do this.
However, in the finalization thread, this order is no longer used, and thus if the stream was placed on the list before the objects that referenced it, the stream is finalized, and thus closed, before the object referencing it.
In other words, what you cannot do is summarized as follows:
You can not access any objects your object refer to, that has finalizers, as you have no guarantee that these objects will be in a usable state when your finalizer runs. The objects will still be there, in memory, and not collected, but they may be closed, terminated, finalized, etc. already.
So, back to your question:
Q. Can I use strings in finalizer method?
A. Yes, because strings do not implement a finalizer, and does not rely on other objects that has a finalizer, and will thus be alive and kicking at the time your finalizer runs.
The assumption that made you take the wrong path is the second sentence of the qustion:
Inside finalizers I can't use other objects because they could have been garbage-collected already.
The correct sentence would be:
Inside finalizer I can't use other objects that have finalizers, because they could have been finalized already.
For an example of something the finalizer would have no way of knowing the order in which to correctly finalize two objects, consider two objects that refer to each other and that both have finalizers. The finalizer thread would have to analyze the code to determine in which order they would normally be disposed, which might be a "dance" between the two objects. The finalizer thread does not do this, it just finalizes one before the other, and you have no guarantee which is first.
So, is there any time it is safe to access objects that also have a finalizer, from my own finalizer?
The only guaranteed safe scenario is when your program/class library/source code owns both objects so that you know that it is.
Before I explain this, this is not really good programming practices, so you probably shouldn't do it.
Example:
You have an object, Cache, that writes data to a file, this file is never kept open, and is thus only open when the object needs to write data to it.
You have another object, CacheManager, that uses the first one, and calls into the first object to give it data to write to the file.
CacheManager has a finalizer. The semantics here is that if the manager class is collected, but not disposed, it should delete the caches as it cannot guarantee their state.
However, the filename of the cache object is retrievable from a property of the cache object.
So the question is, do I need to make a copy of that filename into the manager object, to avoid problems during finalization?
Nope, you don't. When the manager is finalized, the cache object is still in memory, as is the filename string it refers to. What you cannot guarantee, however, is that any finalizer on the cache object hasn't already run.
However, in this case, if you know that the finalizer of the cache object either doesn't exist, or doesn't touch the file, your manager can read the filename property of the cache object, and delete the file.
However, since you now have a pretty strange dependency going on here, I would certainly advice against it.
Another point not yet mentioned is that although one might not expect that an object's finalizer would ever run while an object is in use, the finalization mechanism does not ensure that. Finalizers can be run in an arbitrary unknown threading context; as a consequence, they should either avoid using any types that aren't thread-safe, or should use locking or other means to ensure that they only use things in thread-safe fashion. Note finalizers should use Monitor.TryEnter rather than Monitor.Enter, and endeavor to act as gracefully as possible if a lock is unexpectedly held. Note that since finalizers aren't supposed to run while an object is still in use, the fact that a lock was unexpectedly held will often suggest that a finalizer was run early. Depending upon the design of the code which uses the lock, it may be possible to have the finalizer set a flag and try again to acquire the lock, and have any other code which uses the lock check after releasing it whether that flag is set and, if so, reregister the object for finalization.
Handling finalization cleanup correctly in all threading scenarios is difficult. Finalization might not seem complicated, but no convenient automated mechanisms exist by which objects can ensure that finalizers won't run while the objects in question are in use. Consequently, finalizers have a lot of subtle thread-safety issues. Code which ignores such issues will "usually" work, but may sometimes fail in difficult-to-diagnose ways.
You can call the dispose method inside your finalizer and have the file cleanup code in the Dispose method. Along with that you can also pass a boolean to your dispose method that indicates that you are invoking it from the finalizer.
For an excellent reference on the proper usage of Dispose and Fianlizers , read this Proper use of the IDisposable interface

How do I track down where I've been leaking IDisposable objects from?

I've been debugging some code recently that was a bit memory leaky. It's a long running program that runs as a Windows service.
If you find a class wearing an IDisposable interface, it is telling you that some of the resources it uses are outside the abilities of the garbage collector to clean up for you.
The reason it is telling you this is that you, the user of this object, are now responsible for when these resources are cleaned up. Congratulations!
As a conscientious developer, you are nudged towards calling the .Dispose() method when you've finished with the object in order to release those unmanaged resources.
There is the nice using() pattern to help clean up these resources once they are finished with. Which just leaves finding which exact objects are causing the leakyness?
In order to aid tracking down these rogue unmanaged resources, is there any way to query what objects are loitering around waiting to be Disposed at any given point in time?
There shouldn't be any cases where you don't want to call Dispose, but the compiler cannot tell you where you should call dispose.
Suppose you write a factory class which creates and returns disposable objects. Should the compiler bug you for not calling Dispose when the cleanup should be the responsibility of your callers?
IDisposable is more for making use of the using keyword. It's not there to force you to call Dispose() - it's there to enable you to call it in a slick, non-obtrusive way:
class A : IDisposable {}
/// stuff
using(var a = new A()) {
a.method1();
}
after you leave the using block, Dispose() is called for you.
"Is there any way to detect at the end of the program which objects are loitering around waiting to be Disposed?"
Well, if all goes well, at the end of the program the CLR will call all object's finalizers, which, if the IDisposable pattern was implemented properly, will call the Dispose() methods. So at the end, everything will be cleared up properly.
The problem is that if you have a long running program, chances are some of your IDiposable instances are locking some resources that shouldn't be locked. For cases like this, user code should use the using block or call Dispose() as soon as it is done with an object, but there's really no way for a anyone except the code author to know that.
You are not required to call the Dispose method. Implementing the IDisposable interface is a reminder that your class probably is using resources such as a database connection, a file handle, that need to be closed, so GC is not enough.
The best practice AFAIK is to call Dispose or even better, put the object in a using statement.
A good example is the .NET 2.0 Ping class, which runs asynchronously. Unless it throws an exception, you don't actually call Dispose until the callback method. Note that this example has some slightly weird casting due to the way Ping implements the IDisposable interface, but also inherits Dispose() (and only the former works as intended).
private void Refresh( Object sender, EventArgs args )
{
Ping ping = null;
try
{
ping = new Ping();
ping.PingCompleted += PingComplete;
ping.SendAsync( defaultHost, null );
}
catch ( Exception )
{
( (IDisposable)ping ).Dispose();
this.isAlive = false;
}
}
private void PingComplete( Object sender, PingCompletedEventArgs args )
{
this.isAlive = ( args.Error == null && args.Reply.Status == IPStatus.Success );
( (IDisposable)sender ).Dispose();
}
Can I ask how you're certain that it's specifically objects which implement IDisposable? In my experience the most-likely zombie objects are objects which have not properly had all their event handlers removed (thereby leaving a reference to them from another 'live' object and not qualifying them as unreachable during garbage collection).
There are tools which can help track these down by taking a snapshot of the managed heap and stacks and allowing you to see what objects are considered in-use at a given point in time. A freebie is windbg using sos.dll; it'll take some googling for tutorials to show you the commands you need--but it works and it's free. A more user-friendly (don't confused that with "simple") option is Red Gate's ANTS Profiler running in Memory Profiling mode--it's a slick tool.
Edit: Regarding the usefulness of calling Dispose--it provides a deterministic way to cleanup objects. Garbage Collection only runs when your app has ran out of its allocated memory--it's an expensive task which basically stops your application from executing and looks at all objects in existance and builds a tree of "reachable" (in-use) objects, then cleans up the unreachable objects. Manually cleaning up an object frees it before GC ever has to run.
Because the method creating the disposable object may be legitimately returning it as a value, that is, the compiler can't tell how the programming is intending to use it.
What if the disposable object is created in one class/module (say a factory) and is handed off to a different class/module to be used for a while before being disposed of? That use case should be OK, and the compiler shouldn't badger you about it. I suspect that's why there's no compile-time warning---the compiler assumes the Dispose call is in another file.
Determining when and where to call Dispose() is a very subjective thing, dependent on the nature of the program and how it uses disposable objects. Subjective problems are not something compilers are very good at. Instead, this is more a job for static analysis, which is the arena of tools like FxCop and StyleCop, or perhaps more advanced compilers like Spec#/Sing#. Static analysis uses rules to determine if subjective requirements, such as "Always ensure .Dispose() is called at some point.", are met.
I am honestly not sure if any static analyzers exist that are capable of checking whether .Dispose() is called. Even for static analysis as it exists today, that might be a bit on the too-subjective side of things. If you need a place to start looking, however, "Static Analysis for C#" is probably the best place.

Categories

Resources