Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object
Completely Killing-Off an Object Completely Killing-Off an Object
Completely Killing-Off an Object
Go Back  Xtreme Visual Basic Talk > > > Completely Killing-Off an Object


Reply
 
Thread Tools Display Modes
  #1  
Old 06-20-2010, 07:19 PM
izzy4505 izzy4505 is offline
Regular
 
Join Date: Dec 2004
Location: IL, USA
Posts: 84
Default Completely Killing-Off an Object


Is there a method to completely kill off an instance of an object? For example, if I have an instance of a class created like this:

Code:
Dim bah as New SomeClass()
Later on, I should be able to do this to get rid of it, right?

Code:
bah=Nothing
It was my assumption that if there were no more references, the garbage collector would come by and handle things. Well then I ran into a problem where I did an AddHandler on an event of SomeClass. I discovered that calling RemoveHandler prior to setting the variable to Nothing fixed my problem.

My problem doesn't seem to be completely fixed though! It seems that instances of that class are still hanging around, because I'm still getting events fired from them. Is there a better way to kill an instance?

(Moderator: Please excuse the double post... I had previously posted this in Legacy General by mistake.)
Reply With Quote
  #2  
Old 06-20-2010, 07:37 PM
lordofduct's Avatar
lordofduct lordofduct is offline
Centurion
 
Join Date: May 2010
Location: south florida yo
Posts: 120
Default

garbage collection will remove those objects who have 0 references... an event listener can create an implicit reference at times that can hold things in memory. Using WithEvents makes dealing with event management easier (no need to call AddHandler OR RemoveHandler ever). Speaking of, on a side note, it'd be nice if they added a feature to VB where WithEvents worked with Arrays as well.

Furthermore garbage collection doesn't run immediately after you set something to Nothing. It runs every once in a while when the run time feels it is necessary (several things come into play in deciding if it feels it's necessary). Of course you can override that and force the garbage collector to clean up... be warned it's a costly process so only do it when you know you're in down time.

For objects that MUST be cleaned up immediately (stop doing things and the sort) you may want to consider making the class for that object implement IDisposable. This basically describes a method on the class to 'dispose' the object. When you're done with an object you call the Dispose function and the object cleans up all the stuff it's doing inside and makes sure to not do anything from that point forward (i.e. fire events and stuff).
__________________
I'm a turtle... woooo
Reply With Quote
  #3  
Old 06-20-2010, 07:38 PM
izzy4505 izzy4505 is offline
Regular
 
Join Date: Dec 2004
Location: IL, USA
Posts: 84
Default

I found the bug in my code where setting an object to nothing wasn't actually happening, but I am still curious if there is another method. Is there a general Object.RemoveAllReferences sort of thing?
Reply With Quote
  #4  
Old 06-20-2010, 07:39 PM
izzy4505 izzy4505 is offline
Regular
 
Join Date: Dec 2004
Location: IL, USA
Posts: 84
Default

Quote:
Originally Posted by lordofduct View Post
garbage collection will remove those objects who have 0 references... an event listener can create an implicit reference at times that can hold things in memory. Using WithEvents makes dealing with event management easier (no need to call AddHandler OR RemoveHandler ever).

Furthermore garbage collection doesn't run immediately after you set something to Nothing. It runs every once in a while when the run time feels it is necessary (several things come into play in deciding if it feels it's necessary). Of course you can override that and force the garbage collector to clean up... be warned it's a costly process so only do it when you know you're in down time.

For objects that MUST be cleaned up immediately (stop doing things and the sort) you may want to consider making the class for that object implement IDisposable. This basically describes a method on the class to 'dispose' the object. When you're done with an object you call the Dispose function and the object cleans up all the stuff it's doing inside and makes sure to not do anything from that point forward (i.e. fire events and stuff).
Thanks, that's exactly what I was looking for!
Reply With Quote
  #5  
Old 06-20-2010, 07:52 PM
lordofduct's Avatar
lordofduct lordofduct is offline
Centurion
 
Join Date: May 2010
Location: south florida yo
Posts: 120
Default

do notice, calling Dispose won't take it out of memory... it only does whatever you define the Dispose method to do. The Dispose method aught to stop doing all things internally.

You will still have to remove all references manually and allow garbage collection to actually destruct the object.
__________________
I'm a turtle... woooo
Reply With Quote
  #6  
Old 06-20-2010, 07:55 PM
izzy4505 izzy4505 is offline
Regular
 
Join Date: Dec 2004
Location: IL, USA
Posts: 84
Default

Yep, that is my intention. There isn't a lot that my class does right now internally, but I will start implementing IDisposable.

Thanks again.
Reply With Quote
  #7  
Old 06-21-2010, 10:28 AM
AtmaWeapon's Avatar
AtmaWeaponCompletely Killing-Off an Object AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

(This is somewhat tangential but still relevant.)

Quote:
Using WithEvents makes dealing with event management easier (no need to call AddHandler OR RemoveHandler ever). Speaking of, on a side note, it'd be nice if they added a feature to VB where WithEvents worked with Arrays as well.
I'm confident this isn't true in a general sense. If the objects that handle the events have a shorter lifetime than the object declaring the events, you will always leak. I wasn't sure though, so I made an experiment and tested it.

This is my hypothesis: WithEvents/Handles does not automatically remove event handlers if you destroy the control. I suspect this is true because it was designed for a case where the control is created when the form is created and destroyed when the form is destroyed; this scenario has no need for event handler removal.

I've been through some of the background in recent posts. Here's why event handlers can keep objects alive. Here's how the Handles clause, which is what you use WithEvents for, works.

After reading the above, you'll understand two things. First, if you don't remove event handlers manually the class that handles the event will still have a GC root. Second, WithEvents automatically sets up an event handler and expects to be used with an object whose lifetime is tied to the declaring class.

A hypothesis is worthless if you don't test it. The attached project does just that. The ClassWithAnEvent class has an event and supports a Singleton instance for reasons that will become clear later. The Handler class holds the singleton as a WithEvents instance and uses a Handles clause to handle its event. It also performs a small amount of reference counting; only the GC can call the Finalizer so this should work relatively well.

The test itself creates some number of Handler objects, then drops the references to them. It keeps track of the objects using the WeakReference class so they can be destroyed later.

The first test is a control, to prove that my code for tracking references is semi-reliable. It proves that at the beginning there are 10 total objects, and at the end there are 0.

The next test uses the Handler class and doesn't remove WithEvents. If the handlers are automatically removed, the GC should finalize at least one item. It creates 10 references, drops the references, and no finalizers are called. Hypothesis proved. (Note I use the weak references to try and clean up the references; there is one mysterious root left over. I tried using WinDbg to find what is going on but it will have to be a topic for another day.)

The final test uses the Handler class and removes the event handler before dropping references. The initial count may be more than 10 due to the lingering references from the last run. It doesn't matter; we should expect to see less than this number of references when the test is finished. Sure enough, on my machine the final reference count is 10 less than the initial count. Hooray!

Conclusion:
WithEvents is not an easy way to get automatic cleanup of event handlers. WithEvents is an easy way to handle events for objects that will die with the class. This is most commonly controls on the design surface, but I suppose if you plan well you could use it for dynamically created objects.
Attached Files
File Type: zip WithEventsReferenceDemo.zip (12.8 KB, 0 views)
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #8  
Old 06-21-2010, 02:47 PM
snarfblam's Avatar
snarfblamCompletely Killing-Off an Object snarfblam is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Apr 2005
Location: USA
Posts: 896
Default

Here's my understanding of WithEvents. When compiled, a WithEvents variable is transformed into a property, which includes event wiring code. When that "variable" (property) is assigned, any handlers declared with a handles clause are wired to the assigned object's events. The proper way to un-wire those events is to assign null (Nothing) to the WithEvents variable. This is how WithEvents makes event managing easy. It's easier to set a variable to null than it is to unwire a number of miscellaneous events and set the variable to null.

And WithEvents is useful not only for UI objects, but any object that might raise an event. This is also why it does not unwire events when you destroy a control. WithEvents has no concept if a control or disposal. All WithEvents knows is what object is assigned to a variable. When you dispose a control, there is still an empty shell there, it still has events, and it is still assigned to the variable. Just set it to null.

Contrast this with C#, where all events are wired imperatively instead of declaratively. Because the wiring is not automatic it is easy to mismatch your "AddHandlers" and "RemoveHandlers", resulting in a potential memory leak. This is one feature I think VB got really, really right and I think it's a shame that nobody seems to miss it in the C# world, because that means C# will never get a WithEvents. I hate having to wrap my variables with properties containing unsightly blocks of event wiring code, but it seems like the only sure way to manage events in C#.
__________________
C# _VB.NET _
Reply With Quote
  #9  
Old 06-21-2010, 03:13 PM
AtmaWeapon's Avatar
AtmaWeaponCompletely Killing-Off an Object AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

snarfblam's post is correct; I double-checked in Reflector because I was skeptical

Still, that means WithEvents is only going to work with single-instance variables declared at compile time. I'd argue the most common source of leaked events are multiple instances of objects generated at runtime. I vaguely remember being confused once when I tried to make a WithEvents array variable; if this isn't a fabricated memory then it makes more sense now.

In contrast to your statement snarfblam, I hate when the compiler does stuff by magic. I had no idea setting a WithEvents variable to Nothing did the automatic unwiring, and I've been using VB .NET for 7 years. I've never seen anything mention it at all, despite having a particular interest in events and their implementation. My problem with a syntactic sugar approach like this is if a user finds out they can't use WithEvents with a runtime-declared variable, they might not understand that WithEvents is what does the automatic unwiring and thus won't know that setting the new variable to Nothing won't do it. I'm probably just a little paranoid.

I wouldn't hold my breath for seeing it in C# either; it doesn't match the language's design. VB gets a lot more syntactic sugar than C#, while C# tends to be much more imperative. The sugar would be nice in C#, but there is value in having your IL be nothing more than what you asked the computer to do.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #10  
Old 06-22-2010, 02:50 PM
snarfblam's Avatar
snarfblamCompletely Killing-Off an Object snarfblam is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Apr 2005
Location: USA
Posts: 896
Default

Atma, consider event declarations in VB and C#:
Code:
Public Event Foo As EventHandler
public event EventHandler Foo;
Each single line of code there actually produces a field declaration, two methods, and event meta-data in the IL. How much of that is directly represented in code, in either language? Why should C# approach event declaration so differently from event consumption.

Don't get me wrong, I can obviously see how one can overlook the finer mechanics of WithEvents, but it struck me as pretty straightforward. You have a variable with associated event handlers. What happens if the variable is set to null? If one understands that event handlers constitute a GC root, the implications should lead you to that question. The real gotcha is how tempting it is to think of the event handler as having a reference to the event source when it is really the other way around.

As for WithEvents in C#, especially with C#'s syntax, I see no hidden magic here.
Code:
private withevents System.Windows.Forms.Button button1 {get; set;}
A pipe dream, I know. I like to dabble in the fantastical. Izzy, sorry for hijacking your thread.
__________________
C# _VB.NET _
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object Completely Killing-Off an Object
Completely Killing-Off an Object
Completely Killing-Off an Object
 
Completely Killing-Off an Object
Completely Killing-Off an Object
 
-->