Hi craig,
craig said:
I do have a custom data-binding object that handles events that are raised
by controls on my form. However, the only reference to that custom
data-binding object is held by the form itself. I think that in a case like
that, I don't have to unhook the event handlers, because when the form is
destroyed, the custom data binding object is destroyed along with it.
Correct? the
form
Actually that is a HUGE mistake. I've shouldn't say that. Sorry. Where was
my head when I wrote that?!
It is the other way arround. You have to unhook all events you form has
hooked, but you don't have to do that for internal objects that will be
garbage collected along with the form (most of the cases). But if the form
has hooked an event of an object which is going to be alive longer than the
form you have to onhook them. Otherwise they will keep the form alive. Once
again the event provider collects the delegate objects which are the
references that's why the form as a subscriber have to unhook those events.
Anyways, I believe, the place of those unhookings is not in the Dispose
method. Because if the Dispose is not call explicitly and is left for the GC
and the class finalizer. That object will stay alive as long as the event
provider. Why? Because the delegate (event) is keeping reference to the form
and GC won't consider it for finalization. With forms you are kind of safe
because the are automatically disposed when are closed, but it may be (and
it is ) not the case with other objects. So, keep Dispose for releasing
unmanaged resources.
However you don't have to do this unhooking in your case because haw you
said the objects are held by the form and not referenced form anywhere
Also, as I mentioned earlier, I have a forms collection that is holding
references to all of the forms the user opens. As the user closes those
forms, the IsDisposed properties of the forms becomes set to true.
Periodically, I need to examine the forms collection and remove forms for
which IsDisposed is set to true so that the GC can release their
resources.
IsDisposed == true means that the resources has been already released. The
form is usless as a UI control. However the Form object is alive on the heap
and you can use all non UI properties (usually those are your own data
properties)
In your case you have to remove the form from the collection in order to be
removed from the memory (some times when GC decides so)
What is the best way to cycle through a collection and remove members that
meet a certain condition? I don't think I can use a foreach or for
construct because each time I remove a member of the collection, the
collection changes and the construct counter goes out of sync.
1. No, you can't use enumerator returned by collections' GetEnumerator()
method. *foreach* loop uses that enumerator so you cannot used it as well.
Ofcourse you can write your own enumerator that can make it possible.
Refere to this aricle for how to write such an enumerator object
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp01212002.asp
2. You do can use *for* and *while* loops as long as that collection of
yours support indexing and you maintain properly the index. For example:
int index = 0
while(index < col.Count)
{
if(((Control)col[index]).IsDisposed) col.RemoveAt[index];
else index++;
}
You can use *for* loop in a similar manner.
3. If the collection doesn't support indexing you can clone the collection
and loop through the copy and remove the items from the original. This, BTW,
is how the the enumerator in 1.) works. Then you can leave the copy of the
collection and it will be collected by GC along with the forms
Assuming the collection implements ICollection (just to make the things
easier)
ArrayList temp = new ArrayList(col);
foreach(Control ctrl in copy)
{
col.Remove(ctrl);
}
As long as temp is local variable for some method you don't have to set
temp = null because it will become unreferenced as soon as the variable goes
out of scope. In reality the temp collection will be eligible for GC even
before the end of the scope of the variable (as soon as no code uses that
variable).
4. You can hook all forms Closed event. You should use the same event
handler for all of them in the as a responce of the event you can remove the
form form the collection.
private void aForm_Closed(object sender, EventArgs e)
{
col.Remove(sender);
}
This is what I suggest.
I could just restart the cycle each time I find and remove a collection
member for which IsDisposed is true until I finally make it through the
entire collection. Would that be the best approach?
Thanks for all the input!!!
Yes, you can do that if you don't like the other solutions.
--
HTH
B\rgds
100>
long
as the
form deleting
all away
all
instead
to
my resource
it You
can or
in resources
that
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/ht
method