WeakReference to IDisposable - c#

I have a class holding a WeakReference pointing to an object implmenting IDisposable. After the object is disposed there is a period of time before it is garbage collected. During that time the WeakReference can still be used. This can result in unexpected behavior because we are now making calls against an object that has been disposed.
Does anyone have a suggested approach for dealing with this, checking the weak reference if the target has been disposed, etc.?
Background:
We have a WinForms application with a controller holding data. Multiple UI controls may be presenting the data at any given time. A form adds and removes the controls (and calls Dispose when it removes them) but is ignorant about what the controls are doing or what data they need. Previously the controls would subscribe to events from the controller to receive notifications when the data was updated. This results in memory leaks. To address this the controller now keeps weak references to the controls, and notifies the ones that are still alive.

Since IDisposable and WeakReference have mutual exclusive semantic you need to choose single one. Combining them is dangerous since after a disposal an object most likely will have inconsistent state which isn't suitable for a reusing. IDisposable implies that you'd like to control the life-cycle of your objects and aren't going to take back. It's like to put something into a dumpster and to say: "I'm done with this thing, now I don't care what happens with that". The WeakReference semantic is like to put something near a dumpster and say: "I'm gonna get back in 30 minutes or so, if noone puts this into this dumpster I'll take it back, but if it's inside I don't care".
Weak references imply that objects referenced by them don't have a long life that's they're good for quick memory reclaim but at the same time they give some chance to be reused so in your case you can rely exclusively on WeakReference<T>:
MyType instance;
if (weakRef.TryGetTarget(out instance))
{
// resurrected, still can use it
}
else
{
// object is collected, the new one should be created
}

Just in case anyone else stumbles across this question they way I resolved it was to make the referenced objects have well defined behavior after being disposed (per the comment by Alexei Levenkov). The easiest way to do this was to ignore function calls after the object had been disposed.
public void OnDataChanged(object model)
{
if (IsDisposed)
{
return;
}
...
// method implementation
}
This was only necessary in the single function being called from the weak reference.
Multi-threading was not an issue as these are UI objects and Invoke and BeginInvoke were already required to make calls modifying them.

Related

C#: How to Dispose a contained object as a result of it's own event?

Background:
I've a got a main object that live on my app's UI thread. This long-lived parent / container object contains a sub-object as a private member that is internally multi-threaded.
Based on some event published from the child / contained object I'd like the parent object to simply Dispose() the child and recreate it.
The contained object owns some unmanaged resources and well as some large managed memory buffers.
I could create an event handler on the top level object that does this, but this means that the object about to be Disposed will be in the call stack of the method call to about to replace it. (!)
This is because the event handler delegate will be called by one of the child object's state handling functions on it's own thread.
This seems...wrong. No?
In particular, the the child's FireAnEvent() method will resume execution after the delegate calls are processed, except that now execution will resume in the context of an already "disposed" object.
Intuitively, I can't see this leading to good things.
Question:
Is there an established C# pattern to destroy a contained object as a result of it's own event?
Or, is there GC magic that makes such a simple event handler good enough somehow?
Or, am I missing some key bit of understanding?
Calling IDisposable.Dispose() doesn't signal anything special to the .NET framework. The only thing you need to do is remove any references to the object you wish to remove. Once this is done and the object is out of the call stack, it will become a candidate for garbage collection.
Note that your object will not necessarily be garbage collected immediately, or even the next time the GC runs; it is merely an assumed eventuality.
The only purpose of IDisposable is to provide a standard means for requesting that an object clean itself up and release resources. You can hold a reference to a "disposed" object for as long as you like, which will prevent the GC from collecting the object. IDisposable.Dispose() is just another method; technically, you can make it do anything you want.
This question has a very nicely detailed answer that may help you understand IDisposable a bit more: Proper use of the IDisposable interface
as mentioned, an IDisposable object is nothing magical. It just lets you use the using shorthand, which is just a shorthand for:
try { // code in the using block }
catch{}
finally{
disposableObject.Dispose()
}
Have you considered incorporating a third type of object into the mix? It is ill advised that contained object be conscious of their container.
Roughly this would be your workflow:
contained object decides it should be restarted.
contained object frees resources.
contained object writes to a queue on a third object (not the containing object).
containing object accesses the queue when you feel you should create new contained objects and reinstantiates the objects. Alternatively adding to the queue raises an event to the container to empty it.
The third object might seem pointless but it would make your life a lot easier if you ever decided to refactor.
Objects which subscribe to events for the purpose of notification should be prepared to receive notifications at any time, even after they have been disposed. The purpose of a notification is to tell an object to do whatever it needs to do in response to something that has happened. If an object can't do anything useful in response to a notification, it should simply not do anything.
Further, the purpose of Dispose isn't to "destroy" an object, nor the resources it contains, but rather to release it from any obligations it may have had to outside objects, and allow it to release any outside entities from any obligations they might have had toward it. In many cases, an object will be useless once it releasing the services of outside entities that were committed to it, and thus objects which have been disposed cannot be expected to be useful; if, as is likely, a method which is called after Disposed cannot satisfy its duties because necessary outside entities have been released, it should throw ObjectDisposedException rather than failing some other way.
Putting these observations together, while many methods on a disposed object should throw ObjectDisposedException, notification event handler methods should not, since they're instructing the object to "do whatever you need to do to meet your obligations, given that something has happened". If an object has been disposed, it has no obligations. Thus, being disposed doesn't prevent an object from satisfying an event handler contract; instead, it allows the object to meet the contract by silently ("successfully") doing nothing.

Is there a reason to remove a method from an event after it has been invoked in Silverlight?

Recently I have come across an increasing number of people who have code similar to the following:
private AsynchronousReader r;
public SynchronousReader()
{
r = new AsynchronousReader();
// My practice is to put this here
// and then never remove it and never add it again
// thus cleaning up the code and preventing constant add/remove.
//r.ReadCompleted += this.ReadCompletedCallback;
}
private ReadCompletedCallback()
{
// Remove the callback to "clean things up"...
r.ReadCompleted -= this.ReadCompletedCallback;
// Do other things
}
public Read()
{
r.ReadCompleted += this.ReadCompletedCallback;
// This call completes asynchronously and later invokes the above event
r.ReadAsync();
r.WaitForCompletion();
}
Folks say that this practice is better than the one I indicated above and have given several reasons specific to Silverlight. They state it prevents memory leaks, threading issues, and even that it is the normal practice.
I have not done much Silverlight, but it seems silly to do this still.
Are there any specific reasons one would use this method instead of just rigging up the callback in the constructor once and for the lifetime of the object?
This is as simple as I could make my example. Ignore the fact that it's a sort of wrapper that turns an asynchronous object into a synchronous one. I'm only curious about the way events are added and removed.
In the case you mention it would make sense to hook it up once, but potentially the objects (parent and/or child) may not get garbage collected as the event handlers still reference them.
According to Marc Gavel here
i.e. if we have:
publisher.SomeEvent += target.SomeHandler;
then "publisher" will keep "target" alive, but "target" will not keep
"publisher" alive.
A more important point to bear in mind might be the lifespan of the child object. If it is the same as the parent, then one-off subscription in the constructor makes more sense. If it is dynamic you will likely want to remove the handlers as I have seen them leak (resulting in multiple callbacks).
Note: If the constructor-only method turns out to leak objects, you can always put an unsubscribe in the Dispose() I guess, but I can't say I have ever seen that.
It sounds like you have two issues:
You're attempting to reuse an object that really should only be used once.
That object needs to get properly cleaned up.
You should really either only use an instance of the SynchronousReader object only once (thus avoiding the two async calls racing with one failing to finish like you mentioned elsewhere) or you should implement IDisposable in order to unsubscribe from the event and prevent the memory leak.
A third solution might be possible: keep the single instance of SynchronousReader, but each call to SynchronousReader.Read would create a new instance of AsynchronousReader (rather than storing it as a private field within the instance). Then you could keep most of the code above which you don't like, but which properly handles event subscriptions.

Disposing of a collection and then it's contents

I have an object, which contains a collection of other objects. I want to dispose of them all by calling the dispose method on the base object. The dispose method of the collection will clear the collection, but it does not dispose of the individual objects it contains. So I need my base object to loop through and dispose of each child object. The last detail is that I want to make sure that the collection is disposed of before the individual objects it contains.
I am thinking I can get this behavior by using Dispatcher.BeginInvoke and a low priority. First passing it the dispose call for the collection and then looping through and disposing each individual item. (pseudo) code looking something like this:
class Foo
{
FooCollection Children;
void Dispose()
{
//unsubscribe from data model events
CurrentDispatcher.BeginInvoke(Children.Dispose, ApplicationIdle, null);
foreach (Foo Child in Children)
{
CurrentDispatcher.BeginInvoke(Child.Dispose, ApplicationIdle, null);
}
}
}
class FooCollection
{
void Dispose()
{
//unsubscribe from data model events
this.Clear();
}
}
Am I on the right track? Or am I just setting myself up with a race condition? i.e. is it possible that the Dispatcher could get around to calling dispose on the collection before the foreach finishes queing up the dispose calls for the children? Is there a better way to get the desired behavior?
It is probably worth noting that each of these classes exposes events, and hooks handlers into other objects. My primary goal is to make sure all of the handlers get cleaned up gracefully when dispose is called.
EDIT (8/24):
The instances of these classes subscribe to events from objects which generally persist for the life of the application. Because of this, the persistent object maintains a reference to each of these instances. I am trying to make sure that each instance unsubscribes from the persistent object's events when the instance is no longer needed.
EDIT 2 (8/30):
This is part of a view model, which represents a data hierarchy retrieved from a web service. The cost of retrieving the data from the web service is high, so the actual data objects returned are cached, generally for the life of the application. The data objects implement ICollectionChanged and IPropertyChanged, the view model objects in question subscribe to these events. The nature of the application is such that user actions will likely cause the view model to be discarded and recreated several times during a session. The nature of the data is such that there will commonly be several thousand nodes in the hierarchy which have to be represented in the model. The primary concerns, as they relate to this question, are:
1) Making sure that the discarded view model unsubscribes from the events of the underlying data model
2) Making sure it is done in such a way that looping through the full hierarchy of the discarded view model does not noticeably impact the user in working with the new instance of the view model.
I have updated the code example to more accurately represent the situation. So the question remains. Will this code give me the expected result in that the collection, and then all of its children, will be queued up for disposal before any object actually gets disposed, and then some time later the thread will start disposing them when it has idle time? Or is it going to create a race condition where the collection could possibly be disposed of before I have finished looping through it?
Most posters have focused on the fact that the collection gets cleared, in all honesty clearing the collection is probably unnecessary, but it is a bit of a habit, and I consider it to be good housekeeping.
Check this link out, it has a nice explanation of garbage collection with regards to event handlers: What best practices for cleaning up event handler references?
It really depends on how your events line up. If you have objects that receive events from other, more persistent objects, they will stick around to receive those events until the event sources are GCed. This indicates that your dispose method should probably clear the events that you are hooked up to (with the -= operator) if you really need to reclaim this memory (how big are these objects? what's the system you are running this on?) You'll have to call this Dispose method yourself when you're done with the objects...
Clearing the collection is not necessary - just make sure all the references to any objects that you are done with are set to null. When no references exist and no event handlers must be maintained, the GC will collect the object.
I also wouldn't worry about the dispatcher.. unsubscribing from events shouldn't pose a performance issue.
You don't choose when to dispose managed objects - the GC does. You can't dispose a collection before you dispose its children.... because you can't dispose a collection at all! You can only prepare a managed object for garbage collection, and the way to do that is
(1) Clear event handlers and
(2) Get rid of all the references to the objects you are done with.
The GC will take care of the rest.
You won't be able to guarantee the sequence the dispatcher calls dispose. Given that, it'd be better in my opinion to dispose of the individual items in the collection and then call dispose on the collection.
If the collection is cleared prior to the foreach loop completing you could end up with an exception.
I would suggest you a bit another design. Please note, it's not final code, just to show the idea.
class Bar:IDisposable
{
void Dispose()
{
//do some logic
}
}
class BarCollection:List<Bar>,IDisposable
{
void Dispose()
{
foreach(Bar bar in this){
bar.Dispose();
}
}
}
class Foo
{
BarCollection Children;
void Dispose()
{
CurrentDispatcher.BeginInvoke(Children.Dispose, ApplicationIdle, null);
}
}

Object disposal in .Net

Assuming i have the following classes:
Class MainClass
{
private OtherClass1;
MainClass()
{
OtherClass1 = new OtherClass1();
}
void dispose()
{
OtherClass1 = null;
}
}
class OtherClass1
{
private OtherClass2;
OtherClass1()
{
OtherClass2 = new OtherClass2();
}
}
class OtherClass2
{
}
If i instatiate MainClass and later call dispose method, does the OtherClass1 gets garbage collected (later on)? Or do i have first to clear the reference to OtherClass2?
An object will get garbage collected if it has no references, or the references it does have are from objects that themselves don't have references (and so on).
A way of visualising it, is the garbage collector will walk the object reference graph, following all object references, making a note of ones it gets to (still referenced from somewhere). Any it doesn't get to are eligible for garbage collection as if it didn't get to them then they can't possibly be used.
See here for in-depth info (particularly "The Garbage Collection Algorithm"): http://msdn.microsoft.com/en-us/magazine/bb985010.aspx
So yes, it'll be eligible to be GC'd.
Also, if you have a dispose method you really should implement IDisposable.
In the code as provided, you don't have to null anything, you can safely remove your dispose() and all will be well.
If your OtherClass1 and/or OtherClass2 are managed resources, ie they implement the IDisposable interface then your code is not good enough. You then will have to chain the Dispose:
class MainClass : IDisposable
{
private OtherClass1;
MainClass()
{
OtherClass1 = new OtherClass1();
}
public void Dispose()
{
OtherClass1.Dispose();
// OtherClass1 = null; // not needed
}
}
If there is no other reference to it, it may at some time be garbage collected. Note that this is not deterministic, you cannot rely on it being collected in a specific timespan.
In general, you shouldn't worry too much abot this, the GC in .NET can by design handle circular references etc. without any problem. Setting fields to null is usually not required. The Dispose method is usually used to release unmanaged resources, such as database connections etc. in a deterministic fashion; it's not about freeing the memory of the object being disposed.
The best practice is to implement IDisposable interface and implementing the Dispose() method.
At Dispose(), you just release the resources used by your object such as any external resources, COM references, database connections, etc.
In terms of When the object will be garbage collected, it's up to the .NET engine to decide that as they frequently update their disposal algorithm with each release.
In general, when an object is orphan (no variable references it), it will be in the queue to be garbage collected.
You can manually call GC.Collect(); but that's not recommended since it interferes .NET garbage collection mechanism.
The term "Dispose" is a bit of a misnomer, since the Dispose method doesn't delete the targeted object but rather serves a request for the targeted object to do anything that will need to be done before it may be safely abandoned. Essentially, it's a request for the object to put its affairs in order.
The most common situation when a particular object will need to put its affairs in order is when some entities outside of it may be doing something, storing something, refraining from doing something, or otherwise temporarily altering their behavior on its behalf. Note that the entities may be .net objects, other types of OS-recognized objects (GDI handles, etc.), etc. but there's no particular requirement that the entity be any particular kind of thing, nor that they be in the same computer, or even any computer. For an object to puts its affairs in order, outside entities doing, holding, etc. anything on its behalf need to be told that they no longer need to do so. If the entities in question are .net objects that implement IDisposable, the notification would be generally performed by calling their Dispose method.
Note that .net provides a means by which objects can ask to be notified if the system notices that they've been abandoned, and use that as a cue to put their affairs in order. Such notifications may not come in timely fashion, and various factors may cause them to be delayed essentially indefinitely, but the mechanism (called "finalization") is sometimes better than nothing.

In the Dispose(bool) method implementation, Shouldn't one set members to null?

None of the guides/notes/articles that discuss IDisposable pattern suggest that one should set the internal members to null in the Dispose(bool) method (especially if they are memory hogging beasts).
I've come to realize the importance of it while debugging an internal benchmark tool. What used to happen was that, there was this buffer that contained a big array inside it. We used to use a static buffer for the whole benchmark program. Once we're done with the buffer, there was no way we could release this internal array, neither could we make this buffer releasable (as it was static).
So, I believe that, after Dispose() is called, the class should do everything it can so that it releases all the resources it is using and make them available again, even if the object being disposed itself is not collected back by GC, and not setting members to null, thereby, not allowing the internal objects to be collected by the GC implies that the Dispose implementation is not perfect.
What's your opinion on this ?
Releasing any additional references during Dispose is certainly something I try to do, for two reasons:
it allows the inner objects to be garbage collected even if the disposed object is still in scope
if the inner objects are disposable, it means we only dispose them once even if Dispose() is called repeatedly on the outer object
For example, I tend to use things like:
if(someDisposableObject != null)
{
someDisposableObject.Dispose();
someDisposableObject = null;
}
(for non-disposable, just set to null)
someNonDisposableObject = null; // etc
You might also want to set any events to null:
someEventHandler = null;
This can help minimise the impact if the caller can't fully release their reference (or simply forgets) at the moment. While you should try to release the outer object (for GC), it is relatively easy to accidentally extend the life of the object, for example via a captured variable (anonymous method/lambda), an event, etc.
If you have a finalizer, then during the GC process there is no benefit doing this, and you shouldn't really call methods on external objects (even Dispose()) - so in short: don't do any of this during a GC sweep.
Maybe I'm missing your point, but once your object is disposed, the root or 'sub-root' it represented relative to it's members has been detached. It seems like you are thinking of garbage collection like a ref count system (which can be done, but ... usually isn't).
Instead, think of it as a many-rooted tree, where every object has branches for what it links to. At the end of the day the 'final roots' are statics and anything instantiated from a 'main' loop.
When the garbage collector runs, the easiest way to think about what it does is to consider that it will walk the list of 'real roots' and apply a 'color' to everything it can 'reach'.
Now, assumed the collector has access to 'everything', whether it was rooted or not. Anything not colored can be cleaned up.
Getting back to your original question, when your object is disposed, one assumes (or at least hopes) that no one references it anymore. If this is the case, it is no longer rooted, and so it will not contribute to 'coloring' anything it touches.
Long story longer - if nulling out members in a Dispose routine is fixing something - I would be you have a different, and real, problem that someone is holding a link to your disposed object, and keeping it 'reachable' when it should not be.
I apologize for what may be the most over-quote-filled message I've ever written, but I'm sort of abusing standard terms.
Well, generally, it's not going to make a difference. The only place where it will make a difference is when you have a reference to an object on the Large Object Heap, the behavior of which you have seen already).
There is a good article on the LOH which goes into this in more detail here:
http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Categories