foreach loops call .dispose() on objects which implement IDisposable automatically. It's a nice feature, but let's say you had the following function:
public COMWrapper GetCOMWrapperByName(string COMWrapperName)
{
List<COMWrapper> COMWrapperList = GetCOMWrappersFromPlace();
foreach(COMWrapper cw in COMWrapperList)
{
if(cw.name == COMWrapperName)
return cs;
}
}
And that COMWrapper's .dispose() method released it's associated COM Object.
As I understand it, the foreach loop would dispose of each COMWrapper at the end of the loop, but then leave the matched COMWrapper since it was returned before reaching the end of the statement.
This becomes a problem, however, for the COMWrapper references left in the COMWrapperList list, as half of them have had their underlaying COM Object RCW wrappers removed without themselves being disposed of. Worse, the REMAINING half of the list has totally unmanaged COM Objects now floating in the ether, and since the COMWrapper objects they exist in haven't been disposed of, it becomes very difficult to traverse the List and call .dispose() appropriately in a finally statement (we don't, after all, want to release COM Objects twice).
Is it possible to determine if a COM Object has been released without catching a ObjectDisposedException exception? Is there a better way to dispose of the remaining COM Objects and their wrappers? Or maybe I'm absolutely misreading this situation and need to reevaluate my base understanding of COM Objects, what am I doing wrong?
foreach doesn't dispose of all of the objects in the sequence being iterated. It only disposes of the IEnumerator object that provides you with the objects being iterated over.
Most resources state that the garbage collector figures that out on its own based on references and that I shouldn't mess with it.
I am wondering if I can explicitly tell the garbage collector that it may dispose an object while still keeping a reference.
What I would like to do is to tell the garbage collector that I currently don't need an object anymore (but might again) and then at a later point when (if) I need the object again I would like to check if it has been disposed already. If it has I simply recreate it, if it hasn't I'd like to "unmark" it from garbage collection until I am done with it again.
Is this possible?
I plan to implement something similar to the Lazy<T> class. Pseudocode:
obj = new DisposeIfNecessary<LargeObject>(() => InitLargeObject());
obj.DoSomething(); // Initializes obj using InitLargeObject()
obj.DisposeIfNecessary(); // This is where the magic happens
... // obj might get disposed at some point
obj.DoAnotherThing(); // Might or might not call InitLargeObject() again
obj.Dispose(); // I will not need it again
The WeakReference class does exactly what you want, using the IsAlive property to check for state before using it.
You can get a "strong" reference to it again via the Target property, which will affect the reference count and stop it from being eligible for collection.
Also note that Dispose doesn't directly relate to garbage collection, so disposing an item (depending on the Dispose implementation) might make it unusable anyway - but again, that is nothing to do with GC. On a general practice note, as mentioned by #HansPassant, calling Dispose on an item (or generally anything claiming to dispose) and then attempting to use it again afterwards is a code smell (or just plain wrong as other developers will expect Dispose to be a last-call method marking the object as unusable from then on).
The WeakReference class will not be responsible for re-creating collected objects, but in conjunction with IsAlive you can handle that logic yourself.
Also, to the point in the comments, the GC doesn't do anything clever with WeakReference in terms of deciding when to collect it in terms of trying to leave WeakReference items until last; it will collect the underlying object as it would others during a run if it is eligible - no special handling and definitely no "cache" behaviour.
I have a model class that has a Saved event. The idea is that if two viewmodels use that model object, if one of them changes it, the other will be updated.
Do I have to remove the event handler when I am no longer using its view model? Here is my code:
protected AbstractEntityViewModel(AbstractEntity ae)
{
this.ae = ae;
ae.Saved += delegate(object o, EventArgs e)
{
base.OnPropertyChanged(null);
};
}
Is this ok, or do I need to change this so that I can -= get rid of the delegate when the viewmodel is no longer used?
Direction of event References
To know whether you really need to detach the event handler, you've first got to understand that:
ae.Saved += delegate(object o, EventArgs e)
{
base.OnPropertyChanged(null);
};
means ae is now referencing this. So the object with the event is referencing the object with the event handler. It's not the other way around (event handler referencing event).
Objects not referenced by GC root can be collected
Furthermore, while ideally objects to be garbage collected are not referenced by any other objects, that is not strictly necessary:
The garbage collector can collect all objects which are not referenced by a GC root in any way (path). This means if you've got an insular graph of objects (objects referencing other objects of the graph, but there is no object outside the graph which is referencing an object inside the graph [no GC root either]), then the entire object graph will eventually be garbage collected. The more intertwined the graph is, the more expensive it is for the GC to collect it. Detaching event handlers helps in dissolving such graphs more speedily.
Correctly cleaning up objects
.Net does not feature Destructors. Instead there is the IDisposable pattern and finalizers (see Implementing Finalize and Dispose to Clean Up Unmanaged Resources).
Long story short:
Finalization methods (~Foo () { } for class Foo) are needed when an object manages unmanaged resources. They are called by the garbage collector when the GC is collecting the object. So the exact moment is not up to you.
Disposable pattern can be used to clean-up managed as well as unmanaged resources. If the object has got unmanaged resources, it must still have a finalizer. Why? The Dispose() method is called by you. There is no guarantee that it's being executed. If the application fails to call the Dispose() method, there's still the GC which calls finalize. So basically doing unmanaged-resource cleanup in Dispose is just a performance improvement (which, under some circumstances, may be very important, unless you want to plug in a few more gigabytes of RAM into the computer...).
If you plan to use a finalizer i absolutely urge you to read the docs on it, because there's quite a few things which i didn't cover here. See Implementing Finalize and Dispose to Clean Up Unmanaged Resources
Your example
To come back to your example, after you construct a AbstractEntityViewModel, it will stay alive as long as the AbstractEntity you've passed to the AbstractEntityViewModel stays alive and vice versa.
But when neither of those two are referenced by a GC root, both of them are garbage collected.
If you detach the event handler, the AbstractEntityViewModel (or rather it's concrete sub-class instance) can be garbage collected even if the AbstractEntity can't.
Also see: Understanding Garbage Collection in .NET
Long and short of it is yes. The secondary object can not be disposed of if the AbstractEntity object still has a reference to it. IF there is a chance that the object will be disposed and the Event is still around (this holds true for static events too) then you need to manually remove the eventhandler or the object will not be disposed.
Events can be though of as being a primitive observer implementation: The subject retains a handler to every subscribed observer, meaning they are unable to be garbage collected. To allow the observer to be garbage collected, it must be removed as an observer from the subject.
The only time where event handlers do not need to be manually removed are when the subject and the observer are the same instance, as the garbage collector will detect the circular reference and subsequently finalize the object.
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
Say I want to make an attached property that attaches a list of object references to a view instance (a DependencyObject/FrameworkElement)...
When does it release all of those references? Will it call Dispose on attached property values if they implement it?
Its perhaps easier to think that "references" never actually get "released". They simply fall in to disuse and can no longer be found by following any chain of reference from the global space or any thread stack. They are then considered garbage and at some point the collector will come and collect the memory they occupy. If they have finalisers it will not collect the memory immediately but place the object on a queue that will call the finaliser first.
A FrameworkElement should not, for all sorts of reasons, call Dispose on any reference held in its value dictionary when it is being unloaded. Primarly because it can't know that its responsible for doing that.
Imagine a scenario in which code elsewhere created a disposable object and also attached it to a framework element. What would happen if that code later attempted to use the object only to find that the framework element had taken it upon itself to dispose it?
It is the responsibility of the code that creates a disposable object to ensure that its disposed at the appropriate point.
Think of dependency properties as key-value pairs in DependencyObjects. When you assign a value to an attached dependency property (or a regular dependency property), this value is put into the dictionary. That means items in the list will be collected by garbage collector when the view itself is garbage collected. Dispose behavior is usual too.