C# memory and dispose related questions - c#

I have the following piece of code, just wanted to check who will call the dispose? is it called automatically.
ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, toolTipText);
Also let say I create a Timer local variable, who will call the dispose, what about memory leaks, as, if I call the dispose right away, the timer event, won't be fired.
Do I need to make sure that in the timer event handler dispose is called, even if I don't have any reference to the timer variable. Also do I need to unregister the event handler for that timer.
Edit:
But how to call dispose on ToolTip, if I call it won't show.
Also why I need to Dispose the Timer, if I don't have any reference.
And Do I need to also unregister the timer event handler?
Also does keeping a reference increases the class memory footprint.

ToolTip registers event handlers on the control on which it is shown. It's Hide() method is automatically called when the form's Deactivate event fires. Which will happen when the form is closed. That in turn ensures that its Windows handle is destroyed and event handlers are unregistered. After that there are no disposable objects left.
You can verify this for yourself with Reflector or the Reference Source. Relevant methods are, in order, BaseFormDeactivate, HideAllToolTips, Hide, ClearTopLevelControlEvents.
You don't have to call Dispose(), you don't have a leak.

Dispose is a method provided to allow you to release the object immediately. For example an exclusive file stream.
Finalize is a method that automatically releases any resources the object is using once it is no longer being used by your program.
You only need to worry about disposing when the object uses exclusive or finite resources. Examples being the file one, or a database connection. (Note that in both these cases Close is equivalent to disposing)
To answer your question, you are not disposing at all, but letting the finalizer run when it needs to.

In .NET the garbage collector will automatically free memory when an object can no longer be referenced from anywhere. When it does so, if the object has a finalizer it calls the finalizer. The finalizer is for cleaning up, usually unmanaged resources.
However, finalizers are expensive (they delay garbage collection on an object, for example) and you cannot tell when it will be run (as you can't tell when the GC will decide to collect it). They are usually left as a last resort for cleaning up things like unmanaged resources.
This is where the IDisposable interface and it's Dispose method comes in. Dispose can also be used to clean up, both managed and unmanaged resources. When you call the Dispose method it cleans up and the object is no longer in a stable, usable state.
If you have a resource which implements IDisposable you can call Dispose on it when you know you are done. That way and resources it is holding on to can be freed up as soon as possible. The usual way of doing this is to wrap it up in a using statement, which will automatically Dispose when the using block is done. e.g.:
using (SomeDisposableObject disposableObject = new SomeDisposableObject())
{
disposableObject.DoSomeStuff();
disposableObject.DoSomeMoreStuff();
}
When the using block is finished (after DoMoreStuff) Dispose is called on disposableObject. Using statements are a lot cleaner than the equivalent code when you take into account exception handling.
In the case of something like ToolTip, which has unmanaged references (a lot of WinForms in a wrapper around the unmanaged Win32 components) it will have a finalizer to make doubly sure the unamanged resources are freed correctly. However, if you call Dispose on the object, the cleanup code is run there and then and the finalizer is suppressed (it won't run when the object is collection by the GC).
So, to answer your question more directly, if you know exactly when an IDisposable is finished with it is a good idea to call Dispose. However, if you don't it is usually ok just to leave it up to the garbage collector to collect it and call the relevant code to correctly cleanup the object.
In the cases of ToolTip and Timer given, I wouldn't worry about calling Dispose on them yourself as I suspect it would be difficult to predict when they will be finished with.

You need to call Dispose on anything that implements IDisposable, or at least make sure something does. For UI components, add them to a form's Controls collection and they'll get disposed when the form closes. For other things you need to keep a reference to them and call dispose appropriately. It may be appropriate to make your class implement IDisposable just to call Dispose on your composed objects.

Generally, it's up to the object registering to an event to un-register - not doing so will create memory leaks. You should not rely on a Dispose method doing so.
Dispose is not called automatically, unless you wrap the object in a using() {} statement, or add it to the objects IContainer instance (if it's a designer class). If it's a class variable, you need to make the containing class implement IDisposable and dispose of the instance in it.

Related

Is it possible to determine an object being disposed right after last object reference freed up?

I'm creating a Memory holder class that wraps around a heap object, and I want to
determine the dispose of the object is very force for GC.
I want something like:
myObj = null; //Immediately call to ~myObj()
The .NET framework and runtime provides two features for applications which use unmanaged resources.
Deterministic cleanup: The IDisposable interface allows code to release resources at a specific time, by explicitly or implicitly calling the Dispose() method. (The using statement in C# provides implicit support for this call.)
Eventual cleanup: In the event users fail to release unmanaged resources by calling the Dispose() method, a finalizer can be used to prevent long-running applications from leaking these resources over time. User code generally should not include user-defined finalizers; instead, create (or use an existing) class which extends SafeHandle and implement the ReleaseHandle method to define the release behavior.
Note that IDisposable.Dispose() is the only supported mechanism for deterministic resource cleanup. Eventual cleanup is a non-deterministic fallback that should be avoided.
No, you can't do this. You should simply use IDisposable as it's meant to be used.
COM objects expect to be notified promptly when they go out of scope, but .NET does not support prompt notification except via Dispose. You should call IUnknown.Release in your dispose method but you must ensure before calling IUnknown.Release that there is no way that anyone might ever try to use that COM object again. Attempting to use a COM object that has after Release, or even simply trying to call Release upon it again, is a recipe for disaster.
I would suggest, therefore, that no reference to the COM object itself ever be released to outside code. Instead, have the class which holds the object forward all requests to the object itself within a lock (to ensure that code doesn't attempt simultaneous accesses), and have your Dispose method acquire the lock, call Release on the object, and then invalidate the reference. Any future attempts to manipulate the object which aren't otherwise trapped will cause a NullReferenceException which isn't brilliant, but is still way better than trying to use a COM object after it is released.

How much work in the Dispose method?

How much work should be done in a Dispose method? In constructors I've always taken the stance that you should only do what is absolutely necessary to instantiate the object. This being the case I've also always taken the approach that you should ONLY be cleaning up open resources when disposing. Closing files, freeing memory, disposing of child disposable object, etc. You shouldn't be doing lengthy processes like touching files, accessing databases and such in the Dispose method.
Am I wrong? Are those action's OK as long as you are handling any possible exceptions so they don't bubble out of the method? I just don't think doing a lot in Dispose is a good idea. I would like to know what the community thinks.
Am I wrong?
No, you are right. In general the Dispose method is used to clean the unmanaged resources that your class might have allocated.
But that's difficult to generalize. There are cases where the Dispose method is simply used to ensure that some operation executes. For example in ASP.NET MVC there's the Html.BeginForm helper which is used like that:
using (Html.BeginForm())
{
}
and all that the Dispose method does is render a closing </form> tag. So as you can see people could be creative with the pattern and it is very difficult to draw conclusions without a specific scenario.
But in the most common situations it's used to release unmanaged resources.
"It depends". What kind of database/file access are we talking about? Say for example that your disposable object is some sort of logger and you use it in the following pattern
using(Logger logger = new Logger())
{
foo.PerformTask();
}
I think it would be perfectly acceptable for logger to write out "Log started" in the constructor "Log Completed" in Dispose.
How much work should be done in a Dispose method?
This depends, are you implementing the IDispose interface just for the convenience of a 'using' statement, or are you implementing the full IDisposable pattern? In the later case of a full disposable pattern it is still acceptable to perform more complex actions provided that you're 'disposing' parameter is true (i.e. you are not in GC).
When you are defining a finalizer that calls the Dispose method there really is not too much to be concerned about. Similar uses/abuses of the IDisposable interface mentioned already be others (i.e. using (Html.BeginForm())) are capable of performing any action. Often this can greatly reduce code complexity and prevent coders from accidentally forgetting to perform some closing action. One down (or up) side to this is that code executes a little differently inside a finally block.
In constructors I've always taken the stance that you should only do what is absolutely necessary to instantiate the object.
Objects, IMHO, should be valid post construction. So if you have a lot of work to do to construct something so be it. Don't think of the workload involved, think of the consumer of you're object and it's usability. Post-construction Initialize() methods suck ;)
This being the case I've also always taken the approach that you should ONLY be cleaning up open resources when disposing. Closing files, freeing memory, disposing of child disposable object, etc. You shouldn't be doing lengthy processes like touching files, accessing databases and such in the Dispose method.
Actually let's break this down a bit...
Disposing from the GC call to the Finalizer
When you implement the IDisposable pattern (not the interface, the pattern, finalizer and all) you are essentially saying that your object has an unmanaged resource that nobody else knows about. That means you have PInvoked a call to Win32's CreateFile, or maybe you called Marshal.AllocHGlobal or something like that. Essentially you likely have an IntPtr instance member you need to do something with to prevent a memory leak. These are the ONLY types of things that should be done when the disposing parameter is false (i.e. called from the finalizer on the GC thread).
Generally you DO NOT call the Dispose method on children. You should not expect any child object to be valid. Simply touching a member of the child object can accidentally 'revive' or resurrect it.
So when you are writing code that executes in a Dispose method called from the Finalizer you have to be careful. You are executing on the GC thread while the rest of your application waits for you. You should perform as few operations as possible to release the unmanaged memory/resource and quit. Never throw an exception and if you are calling an API that may throw you should catch any exception raised. Propagating exceptions back to the GC will prematurely abort the finalizer thread and the remaining objects to be finalized will not have a chance to clean up.
Disposing from the IDisposable.Dispose() method
As I’ve already said, using the Dispose method is safe enough and can safely accommodate any amount of code/process. This is where you would free unmanaged resources, call the dispose method of child objects, flush and close files, etc. Most of the Dispose methods I’ve written do not have an associated Finalizer and therefore do not follow the IDisposable pattern, yet they implement IDisposable just for the convenience of the using statement.
Am I wrong? Are those action's OK as long as you are handling any possible exceptions so they don't bubble out of the method? I just don't think doing a lot in Dispose is a good idea. I would like to know what the community thinks.
You are absolutely right when the dispose method in question is used from a finalizer. You’re assertions about what you should and should not do in a Dispose method should actually be reworded to apply to anything called by a Finalizer. The fact that this is generally done in a method called Dispose is a matter of convention, the IDisposable pattern, but these issues could easily exist in other methods used by the Finalizer.
If an object does something to the state of some outside entities in a way which makes them more useful to that but less useful to everyone else, the Dispose method of the object should do whatever is necessary to restore outside those entities to more generally-useful state. If one wishes to avoid having an object do too much work in Dispose, one should design the object so as never leave any outside entities in a state which would be onerous to clean up.
BTW, Microsoft likes to use the term "unmanaged resources", and gives examples, but never really offers a good definition. I would suggest that an object holds an "unmanaged resource" if an outside entity is altering its behavior on behalf of that object, in a fashion which is detrimental to other objects or entities, and if that outside entity will continue to alter its behavior until the object stops it from doing so.
You should lean toward the conclusion you have already come to. However there are situations where you need to ensure that services are stopped and that could include things like messages being logged for the service shutdown, or saving the current runtime state to data store. This type of disposal usually only applies to things that have a lifestyle that is application scope, meaning they exist the whole time the application is running. So there are situations outside of the expected norm. As is the case with every rule you should follow when writing code.

IDisposable implementation - What should go in 'if (disposing)'

I have been fixing some memory leak issues in a winforms application and noticed some disposable objects that are not Disposed explicitly (developer hasn't called Dispose method). Implementation of Finalize method also doesn't help because it doesn't go in if (disposing) clause. All the static event unregistering and collection clearing have been put in if (disposing) clause. The best practice is calling the Dispose if the object is disposable, but unfortunately this happens sometimes
If there are unmanaged objects, static event handlers and some managed collections that needs to clear when disposing. What's the way to decide what should go in and what should go out of if (disposing) clause.
Dispose method.
// 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)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
It says managed objects should in if (disposing) which executes normally only when explicitly call Dispose method by the developer. If the Finalize method has been implemented and developer forgets to call the Dispose method the execution that comes here through the Finalizer does not go in if (disposing) section.
Below are my questions.
If I have static event handlers that causes memory leaks where should I un-register them? In or out of if (disposing) clause?
If I have some collections that causes memory leaks where should I clear them? In or out of if (disposing) clause?
If I am using third party disposable objects (eg: devExpress winform controls) that I am not sure whether they are managed or unmanaged objects. Let's say I want to dispose them when disposing a form. How can I know what are managed and what are non-managed objects? Being disposable doesn't say that? In such cases how to decide what should go in and what should go out of if (disposing) clause?
If I am not sure something managed or unmanaged what can be the bad consequences of disposing/clearing/unregistering-events out of the if (disposing) clause? Let's say it checks for null before disposing?
Edit
What I mean as event un-registering is something like below. Publisher is a long lived instance and below line is in the subscriber's constructor. In this case subscriber need to unregister the event and dispose before the publisher.
publisher.DoSomeEvent += subscriber.DoSomething;
Broadly, managed resources are disposed inside if (disposing) and unmanaged resources outside of it. The dispose pattern works as such:
if (disposed) {
If this object is already disposed, don't dispose of it a second time.
if (disposing) {
If disposal was requested programatically (true), dispose of managed resources (IDisposable objects) owned by this object.
If disposal was caused by the garbage collector (false), do not dispose of managed resources because the garbage collector may have already disposed of the owned managed resources, and will definitelty dispose of them before the application terminates.
}
Dispose of unmanaged resources and release all references to them. Step 1 ensures this only happens once.
disposed = true
Flag this object as disposed to prevent repeated disposal. Repeated disposal may cause a NullReferenceException at step 2 or 3.
Question 1
Don't dispose of them in the Dispose method at all. What would happen if you disposed of multiple instances of the class? You'd dispose the static members each time, despite them already being disposed. The solution I found was to handle the AppDomain.DomainUnloaded event and perform static disposal there.
Question 2
It all depends if the items of the collection are managed or unmanaged. It's probably worth creating managed wrappers that implement IDisposable for any unmanaged classes you are using, ensuring all objects are managed.
Question 3
IDisposable is a managed interface. If a class implements IDisposable, it's a managed class. Dispose of managed objects inside if (disposing). If it doesn't implement IDisposable, it is either managed and does not require disposing, or is unmanaged and should be disposed outside of if (disposing).
Question 4
If the application terminates unexpectedly, or doesn't use manual disposal, the garbage collector disposes of all objects in random order. The child object may be disposed before it's parent is disposed, causing the child to be disposed a second time by the parent. Most managed objects can safely be disposed multiple times, but only if they've been built correctly. You risk (though, unlikely) causing the gargabe collection to fail if an object is disposed multiple times.
The key to remember here is the purpose of IDisposable. It's job is to help you deterministically release resources that your code is holding, before the object is garbage collected. This is actually why the C# language team chose the keyword using, as the brackets determine the scope that the object and it's resources are required for by the application.
For instance, if you open a connection to a database, you want to release that connection and close it ASAP after you have finished with it, rather than waiting for the next garbage collection. This is where and why you implement a Disposer.
The second scenario is to assist with unmanaged code. Effectively this is anything to do with C++/C API calls to the operating system, in which case you are responsible for ensuring that the code isn't leaked. As much of .Net is written to simply P/Invoke down to the existing Win32 API this scenario is quite common. Any object which encapsulates a resource from the operating system (e.g. a Mutex) will implement a Disposer to allow you to safely and deterministically release it's resources.
However these APIs will also implement a destructor, to guarantee that if you don't use the resource correctly that it will not be leaked by the operating system. When your finalizer is called, you do not know whether or not other objects you were referencing have already been garbage collected, which is why it is not safe to make function calls upon them (as they could throw NullReferenceException), only the unmanaged references (which by definition cannot be garbage collected) will be available to the finalizer.
Hope that helps a bit.
If I have static event handlers that causes memory leaks where should I un-register them? In or out of if (disposing) clause?
Dispose method is called on instances where as static event handler are used at class level. So you should not un-register them at all in dispose. Usually static event handler should be un-register when class is unloading or at some point during the execution of application you derive that this event handler is no more required.
For all manages and un-managed resources better implement IDisposable pattern.
See here
http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspx
and
Finalize/Dispose pattern in C#
It sounds like you mainly have managed objects, i.e. objects that implement IDisposable. Unmanaged code would be things like IntPtr's or handles, which would normally mean calling unmanaged code or P/Invoke to get to them.
As Maheep pointed out, Dispose is not meant for this. When an object is done receiving events it should unregister itself. If that's not possible, consider using WeakReferences instead.
This probably shouldn't go in dispose unless these collections contain objects that need to be disposed. If they are disposable objects then it should go in the "if disposing" block and you should call dispose on each item in the collection.
If it implements IDisposable it's managed
You shouldn't access other managed code objects when called by the finalizer which is what being outside the "if (disposing)" block means.
Unless the sole purpose of a class is to encapsulate some resource(*) which needs to be cleaned up if abandoned, it shouldn't have a finalizer, and Dispose(bool) should never be called with a value of False, but calling Dispose(False) should have no effect. If an inherited class would need to hold a resource requiring cleanup if abandoned, it should encapsulate that resource into an object devoted solely to that purpose. That way, if the main object gets abandoned and nobody else holds any reference to the object encapsulating the resource, that object can perform its cleanup without having to keep the main object alive for an extra GC cycle.
Incidentally, I dislike Microsoft's handling of the Disposed flag. I would suggest that the non-virtual Dispose method should use an integer flag with Interlocked.Exchange, to ensure that calling Dispose from multiple threads will only result in the dispose logic being performed once. The flag itself may be private, but there should be a protected and/or public Disposed property to avoid requiring every derived class to implement its own disposal flag.
(*) A resource isn't some particular type of entity, but rather a loose term that encompasses anything a class may have asked some outside entity to do on its behalf, which that outside entity needs to be told to stop doing. Most typically, the outside entity will have granted the class exclusive use of something (be it an area of memory, a lock, a GDI handle, a file, a socket, a USB device, or whatever), but in some cases the outside entity may have been asked to affirmatively do something (e.g. run an event handler every time something happens) or hold something (e.g. a thread-static object reference). An "unmanaged" resource is one which will not be cleaned up if abandoned.
BTW, note that while Microsoft may have intended that objects which encapsulate unmanaged resources should clean them up if abandoned, there are some types of resources for which that really isn't practical. Consider an object that stores an object reference in a thread-static field, for example, and blanks out that object reference when it is Dispose'd (the disposal would, naturally, have to occur on the thread where the object was created). If the object gets abandoned but the thread still exists (e.g. in the threadpool), the target of the thread-static reference could easily be kept alive indefinitely. Even if there aren't any references to the abandoned object so its Finalize() method runs, it would be difficult for the abandoned object to locate and destroy the thread-static reference sitting in some thread.
What should go in 'if (disposing)'
All Managed objects should go inside if(disposing) clause. Managed objects should not go out side of it (which will be executed through the finalization).
The reason is that Garbage collectors finalization process can execute the Dispose(false) if that class has a Destructor. Normally there is a Destructor only if there are unmanaged resources.Garbage collector's finalization doesn't have a particular order to execute the Finalize method. So, other managed objects may not be in memory by the time finalization occurs.

C# UI events unsubscription - necessary?

I know unsubscription from event IS necessary.
My questions comes from the generated code:
When you modify an ui from the VS editor, and add an event handler to a UI element (ex:
private void BtnSampleClick(object sender, EventArgs e))
When creating this event handling, VS adds this code in the private void InitializeComponent() autogenerated code
this.btnSample.Click += new System.EventHandler(this.BtnSampleClick);
Problem is that VS doesn't add the unsubscription (this.btnSample.Click -= new System.EventHandler(this.BtnSampleClick); ) automatically in the Dispose method of the form.
Normally we should add them there right? If not this will leak to memory leaks?
Wanted to check if there was a reason why VS doesn't perform the unsubscription automatically. Maybe the form is correctly disposed even if we don't do it?
Thanks for helping me shred some light in this matter!
This isn't done, mainly because it's really not necessary in this case. The reason is that your Form is subscribing to events of objects which have a lifetime managed by the form. When the object (ie: the button) is unrooted from a GC perspective, the form will also be unrooted (and closed), so there is no chance of a memory leak. The GC in .NET is smart - circular references like this are not an issue.
Unsubscribing to events is still a good general practice, however. It becomes important if you subscribe to an event on an object which has a lifetime independent of the object which is making the subscription. This is especially true if the object with the event is much longer lived than the subscriber. This case is where event-caused memory leaks tend to occur. For example, if your Form subscribes to an event on a static instance, and forgets to unsubscribe, the form will never get garbage collected, since the delegate reference will keep it "rooted" via the event subscription.
Yes, it is a good practice to unsubscribe explicitly. Although they can cause memory leaks, as long as they are not holding any reference to unmanaged objects, GC can still correctly determine and cleanup in the managed world.
You need not to care about that. Dot.NET framework has a Garbage Collector (GC) that automatically dispose using its own principle (may be when there is no reference to the object left).
That does not mean you will never need to call Dispose function, in some case you intentionally call Dispose() method so that the memory does not run out, or when we work with native dll / Marshal class

Specific questions about C# Dispose Pattern

I have a few basic questions about the Dispose Pattern in C#.
In the following code snippet, which seems to be a standard way of implementing the dispose pattern, you’ll notice that managed resources are not handled if disposing is false. How/when are they handled? Does the GC come along and handle the managed resources later? But if that’s the case, what does the GG.SuppressFinalize(this) call do? Can someone give me an example of disposing of managed resources? Unhooking events comes to mind. Anything else? The way the pattern is written, it seems they would get disposed (later) if you did nothing in the “if (disposing)” section. Comments?
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
// If it is available, make the call to the
// base class's Dispose(Boolean) method
base.Dispose(disposing);
}
// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
Is it true what I read about locks in Dispose(bool) in this thread, How do I implement the dispose pattern in c# when wrapping an Interop COM Object?? It says, “Meta-meta comment - as well as that, it's important that you never acquire locks or use locking during your unmanaged cleanup.” Why is that? Does it apply to unmanaged resources as well?
Finally, does on ever implement a finalizer (~MyClass() in C#) without implementing IDisposable? I believe I read somewhere that finalizers and IDisposable are not necessary (or desirable) if there are no unmanaged resources. However, I do see the use of a finalizer without IDisposable in some examples (see: http://www.codeproject.com/KB/cs/idisposable.aspx as one example)
Thanks,
Dave
This way of implementing the IDisposable pattern is a fail-safe way: In case a client forgets to call Dispose, the finalizer called by the runtime will call Dispose(false) later (Note that this part is missing in your sample).
In the latter case, i.e. when Dispose is called by the finalizer, managed resources will already have been cleaned up because otherwise the object in question would not have been eligible for garbage collection.
But if that’s the case, what does the GC.SuppressFinalize(this) call do?
Running the finalizer comes with additional costs. Therefore it should be avoided if possible. Calling GC.SuppressFinalize(this) will skip running the finalizer and therefore the object can be garbage collected more efficiently.
In general one should avoid relying on finalizers as there is no guarantee that a finalizer will run. Some of the problems with finalizers are described by Raymond Chen in the following post:
When do I need to use GC.KeepAlive?
Nobody got to the last two questions (btw: ask only one per thread). Using a lock in Dispose() is pretty lethal to the finalizer thread. There's no upper-bound on how long the lock might be held, your program will crash after two seconds when the CLR notices that the finalizer thread got stuck. Moreover, it is just a bug. You should never call Dispose() when another thread might still have a reference to the object.
Yes, implementing a finalizer without implementing IDisposable is not unheard of. Any COM object wrapper (RCW) does that. So does the Thread class. This was done because it just isn't practical to call Dispose(). In the case of a COM wrapper because it is just not possible to keep track of all reference counts. In case of Thread because having to Join() the thread so that you could call Dispose() defeats the purpose of having a thread.
Pay attention to Jon Hanna's post. Implementing your own finalizer is indeed wrong 99.99% of the time. You've got the SafeHandle classes to wrap unmanaged resources. You'd need something pretty obscure to not be wrappable by them.
The pattern described above was a matter of dealing eloquently with the overlapping concerns of disposal and finalisation.
When we are disposing, we want to:
Dispose all disposable member objects.
Dispose the base object.
Release unmanaged resources.
When finalising we want to:
Release unmanaged resources.
Added to this are the following concerns:
Disposal should be safe to call multiple times. It should not be an error to call x.Dispose();x.Dispose();
Finalisation adds a burden to garbage collection. If we avoid it if we can, specifically if we have already released unmanaged resources, we want to suppress finalisation as it is no longer needed.
Accessing finalised objects is fraught. If an object is being finalised, then any finalisable members (which would also be dealing with the same concerns as our class) may or may not have already been finalised and will certainly be on the finalisation queue. As these objects will likely also be managed disposable objects, and as disposing them will release their unmanaged resources, we do not want to dispose of them in such a case.
The code you give will (once you add in the finaliser that calls Dispose(false) manage these concerns. In the case of Dispose() being called it will clean up both managed and unmanaged members and suppress finalisation, while also guarding against multiple calls (it is not however thread-safe in this regard). In the case of the finaliser being called, it will clean up unmanaged members.
However, this pattern is only required by the anti-pattern of combining managed and unmanaged concerns in the same class. A much better approach is to handle all unmanaged resources through a class which is concerned only with that resource, whether SafeHandle or a separate class of your own. Then you will have one of two patterns, of which the latter will be rare:
public class HasManagedMembers : IDisposable
{
/* more stuff here */
public void Dispose()
{
//if really necessary, block multiple calls by storing a boolean, but generally this won't be needed.
someMember.Dispose(); /*etc.*/
}
}
This has no finaliser and doesn't need one.
public class HasUnmanagedResource : IDisposable
{
IntPtr _someRawHandle;
/* real code using _someRawHandle*/
private void CleanUp()
{
/* code to clean up the handle */
}
public void Dispose()
{
CleanUp();
GC.SuppressFinalize(this);
}
~HasUnmanagedResource()
{
CleanUp();
}
}
This version, which will be much rarer (not even happening in most projects) has the disposal deal solely with dealing with the sole unmanaged resource, for which the class is a wrapper, and the finaliser doing the same if disposal didn't happen.
Since SafeHandle allows for the second pattern to be handled for you, you shouldn't really need it at all. In any case, the first example I give will handle the vast majority of cases where you need to implement IDisposable. The pattern given in your example should only be used for backwards compatibility, such as when you derive from a class that uses it.
...you’ll notice that managed resources are not handled if disposing is false. How/when are they handled?
You didn't include it in your sample, but often the type will have a destructor which will call Dispose(false). Thus, when disposing is false, you "know" that you're in a finalizer call, and thus should *not* access any managed resources, because they might have already been finalized.
The GC finalization process only ensures that finalizers are invoked, not the order that they're invoked in.
what does the GG.SuppressFinalize(this) call do?
It prevents the GC from adding your object to the finalization queue and eventually calling object.Finalize() (i.e. your destructor). It's a performance optimization, nothing more.
The way the pattern is written, it seems they would get disposed (later) if you did nothing in the “if (disposing)” section
Maybe; it depends upon how the type is written. A major point to the IDisposable idiom is for "deterministic finalizaion" -- saying "I want your resources freed now" and having it mean something. If you "ignore" the disposing=true block and don't "forward" the Dispose() call, one of two things will happen:
If the type has a finalizer, the finalizer for the object may eventually be invoked sometime "later".
If the type doesn't have a finalizer, the managed resource will "leak," as Dispose() will never be invoked on them.
it's important that you never acquire locks or use locking during your unmanaged cleanup.” Why is that? Does it apply to unmanaged resources as well?
It's a sanity issue -- YOUR sanity. The simpler your cleanup code, the better, and it's always a good idea to not throw exceptions from Dispose(). Using locks can result in exceptions or deadlocks, either of which are good ways to ruin your day. :-)
does on ever implement a finalizer (~MyClass() in C#) without implementing IDisposable
One could, but it would be considered bad style.
The normal way for objects to be disposed is by calling it's Dispose() method. When done that way, the SuppressFinalize call removes the object from the finalizer queue, turning it into a regular managed object that can easily be garbage collected.
The finalizer is only used when the code fails to dispose the object properly. Then the finalizer calls Dispose(false) so that the object can at least try to clean up unmanaged resources. As any managed objects that the object references may already have been garbage collected at this stage, the object should not try to clean up them.
Instead of trying to learn about disposition via the pattern, you might want to flip things around and try learning why the pattern is implemented this way based on CLR fundamentals and the intended usage of the IDisposable interface. There's a very good introduction to this that should answer all your questions (and a few you didn't think to ask) at http://msdn.microsoft.com/en-us/magazine/cc163392.aspx.
If your class will hold unmanaged resources directly, or if it might ever be inherited by a descendant class that will do so, Microsoft's dispose pattern will provide a good way to tie together the finalizer and disposer. If there's no realistic possibility that either your class or its descendants will ever hold unmanaged resources directly, you should delete the template code and simply implement Dispose directly. Given that Microsoft has strongly recommended that unmanaged resources be wrapped in classes whose sole purpose is to hold them(*) (and has classes like SafeHandle for precisely that purpose) there's really no need for the template code anymore.
(*) Garbage collection in .net is a multi-step process; first the system determines which objects aren't referenced anywhere; then it makes a list of Finalize'able objects which aren't referenced anywhere. The list, and all objects on it, will be re-declared "live", which will mean all objects referred to by them will also be live. At that point, the system will perform an actual garbage collection; it then will run all the finalizers on the list. If an object holds, e.g. a direct handle to a font resource (unmanaged) as well as references to ten other objects which in turn hold direct or indirect references to a hundred more objects, then because of the unmanaged resource the object will need a finalizer. When the object comes due for collection, neither it nor the 100+ objects to which it holds direct or indirect references will be eligible for collection until the pass after its finalizer runs.
If instead of holding a direct handle to the font resource, the object held a reference to an object which holds the font resource (and nothing else), the latter object would need a finalizer, but the former one would not (since it doesn't hold a direct reference to the unmanaged resource. Only one object (the one which held the finalizer), rather than 100+, would have to survive the first garbage collection.

Categories

Resources