Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / General / December 2004



Tip: Looking for answers? Try searching our database.

owner of class

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Al Meadows - 30 Dec 2004 16:37 GMT
I have an application where I use a lot of class modules.  At least a
hundred, and some of these

Something that I think would help me during debugging is to know what class
objects are currently initialized, what intanciated them (i.e. myclass1
created an instance of myclassX and myclass2 created an instance of myclassX.)

One way I was thinking of doing it was to include a variable or two in each
class module that gets set when the class is created that contains the
specific name of the class (i.e. cAcct might be set goodAcct = new cAcct and
set baddAcct = new cAcct).  Then, add a set of AddToStack/RemoveFromStack
functions to each class that would maintain an inventory of existing class
objects.

What I want to accomplish is to identify possible situations where I
terminate a given object but because I've created circular reference, the
class doesn't terminate until after I terminate one or more other classes.

What I would like to be able to do is have a hidden interface 'feature' that
would display a list of all of the active classes and who called them.  Then,
I could easily tell of a class was still active after I thought it should be
closed.

Example:

Module/Class/Form   Instance Name  Class
===========================
frmMain                   goodAcct          cAcct
frmMain                   badAcct            cAcct
frmMain                   strClass            cString
myClass                   strClass            cString

I don't suppose there is anyway to ask the application itself (i.e. is there
some sort of reachable collection of active classes already) without needing
me to create and manage my own?

Al Meadows
Mike D Sutton - 30 Dec 2004 19:43 GMT
> I have an application where I use a lot of class modules.  At least a
> hundred, and some of these
[quoted text clipped - 31 lines]
> some sort of reachable collection of active classes already) without needing
> me to create and manage my own?

One way of doing this is to have an Attach and Detach method of each class that allows it to store it's parent object, probably the
easiest way of doing this is you have multiple classes in your project is to use an interface which exposes the functionality:

'*** IParentTrack
Public Property Get ParentObj() As Object
End Property

Public Sub AttachParent(ByRef inParent As Object)
End Sub

Public Function DetachParent() As Boolean
End Function
'***

Then each class you need to know it's parent object can simply implement the interface:

'***
Implements IParentTrack

Dim m_ParentObj As Object

Private Property Get IParentTrack_ParentObj() As Object
   Set IParentTrack_ParentObj = m_ParentObj
End Property

Private Sub IParentTrack_AttachParent(ByRef inParent As Object)
   m_ParentObj = inParent
End Sub

Private Function IParentTrack_DetachParent() As Boolean
   IParentTrack_DetachParent = Not (m_ParentObj Is Nothing)
   m_ParentObj = Nothing
End Function
'***

You must remember to call DetachParent() on each before you want to destroy it though otherwise you're left with a circular
reference.  If you don't like this solution then you could store a 'soft pointer' to the parent by using the ObjPtr() function
instead:

'*** IParentTrack
Public Property Get ParentPtr() As Long
End Property

Public Sub AttachParent(ByRef inParent As Object)
End Sub

Public Function DetachParent() As Boolean
End Function
'***

'***
Implements IParentTrack

Dim m_ParentPtr As Long

Private Property Get IParentTrack_ParentPtr() As Long
   IParentTrack_ParentPtr = m_ParentPtr
End Property

Private Sub IParentTrack_AttachParent(ByRef inParent As Object)
   m_ParentObj = ObjPtr(inParent)
End Sub

Private Function IParentTrack_DetachParent() As Boolean
   IParentTrack_DetachParent = (m_ParentPtr <> 0)
   m_ParentObj = 0
End Function
'***

This doesn't quite give you the flexibility of the first solution, but doesn't create any circular references.  If you need to get
back to the parent object from the pointer then you can use this function:

'***
Private Declare Sub PutDWord Lib "MSVBVM60.dll" Alias _
   "PutMem4" (ByRef inDst As Any, ByVal inSrc As Long)

...

Private Function ResolveObjPtr(ByVal inPtr As Long) As Object
   Dim TempObj As Object

   If (inPtr) Then
       Call PutDWord(TempObj, inPtr)
       Set ResolveObjPtr = TempObj
       Call PutDWord(TempObj, 0&)
   End If
End Function
'***

If the parent object has already been released though, this will give you back an invalid object which will more thank likely kill
the IDE if you attempt to use it, so be careful when using it..
If you're in a position to use a class factory for your object creating then it's possible to add parent/child relationships
directly into it including communication between the parent and child classes for when either gets destroyed - Have a look at the
class factory and subject/observer design patterns if you want to know more on this approach.
Hope this helps,

   Mike

- Microsoft Visual Basic MVP -
E-Mail: EDais@mvps.org
WWW: Http://EDais.mvps.org/
Ralph - 30 Dec 2004 23:31 GMT
> > I have an application where I use a lot of class modules.  At least a
> > hundred, and some of these
[quoted text clipped - 133 lines]
> E-Mail: EDais@mvps.org
> WWW: Http://EDais.mvps.org/

In addition to Mike's sage advice and suggestions I would like to add one
'Gotcha'. When dealing with VB 'references' be aware that there are
situations where the actual 'COM' reference count and the count you are
maintaining are not exactly the same. (Objects are available for destruction
when the 'COM' Reference count goes to zero.) While you weren't necessary
attempting to maintain COM reference counts - I though I would warn you,
just in case in the heat of the moment, you ever accidently attempt to make
that comparison.

Also you might want to take a look at the mechanism employed by the VB Class
Builder Wizard for displaying a count when classes are created and
destroyed. [View::Options "Include Debug code in Initialize and Terminate
events"].

It is a very simple, and definitely less elegant process, but can be very
useful for isolating problems during development. Also note how you can use
compiler directives to instrument your code only during debugging sessions.
Something you might like to apply in conjuctions with Mike's suggestions.

[You can replace the Debug.Print statements with the Win32 API
OutputDebugString() call and then use a debug viewer to view and track
messages/counts. (www.sysinternals.com)]

hth
-ralph
J French - 31 Dec 2004 11:31 GMT
On Thu, 30 Dec 2004 08:37:01 -0800, "=?Utf-8?B?QWwgTWVhZG93cw==?="
<AlMeadows@discussions.microsoft.com> wrote:

>I have an application where I use a lot of class modules.  At least a
>hundred, and some of these
[quoted text clipped - 18 lines]
>I could easily tell of a class was still active after I thought it should be
>closed.

<snip>

A simple halfway house is to stick code in the Initialize and
Terminate Events of every Class, UC and Form

That code 'registers'/'unregisters' itself with a dinky utility in a
BAS module that maintains an Array of names (and I suggest pseudo
handles)

As a starter look at :

 Private Sub Command1_Click()
     Me.Print TypeName(Me)
 End Sub

Consider this :
    Private cmnHandle As Integer

    Private Sub Class_Initialize
           cmnHandle = DbgMod.RegObj( Me )
    End Sub

And in DbgMod.bas

    Public Function RegObj( Obj As Object ) As Integer
          Dim S As String
          S$ = TypeName( Obj )  
          RegObj = Local_StoreRefStr( S$ )
    End Function

On return the Object 'knows' its own 'Handle', so in the
Class_Terminate event you can tell DbgMod.bas to delete that reference
from the list it is holding

    Call DbgMod.UnRegObj( cmnHandle )

To get to the next stage of your Wish List you give each Class a
property or a Method that takes the Parent/Creator and appends that to
the interesting data in DbgMod.bas
- obviously via the Class

Something like :
    Call oMyObj.RegParent(  Me )  ' if Me is an Object

The nice thing is that at any point one can do a MsgBox (or similar)
of all living Objects - nice to see an inventory of Objects

In my case I have never bothered to record the ancestry, because as
soon as I find a little sucker that refuses to 'die on demand',  I
simply hunt it down, locate its life support machine, and ensure that
it gets switched off.
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.