Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ActiveX EXE: How to destroy object?

Status
Not open for further replies.

nickd87

Technical User
Jan 18, 2006
110
AU
Hi

I have a standard EXE that makes an out-of-process call to an ActiveX EXE which does its thing, then raises an event, which the standard EXE consumes.

Obviously, since the ActiveX EXE raises events, the object is declared with "WithEvents" in a form, and is then instantiated when the call is made within a module.

Because the ActiveX EXE raises its events in its own time (ie I don't sit there blocking, waiting), how do I destroy the object when I'm done with it? I will be finished with it when I get an event back. Do I destroy it in the standard or ActiveX EXE?

At the moment, the ActiveX EXE object is not being destroyed (because when I get an event, I don't know from which instantiation it came from) when it's finished, so the thread count keeps going up and up and up and up, until disaster strikes :)

Any ideas?

Thanks,

Nick
 
Destroy: you mean "release reference."

Beyond this there are rules that govern object lifetime.

Without seeing some code (and it's a crime how many people can't seem to pare down their code to a simple example to illustrate their problem) it is hard to see where you are going wrong.


There is no magic here. Most likely you have circular object references, objects that load Forms (hidden or not), etc. and you are not releasing them when required.

A really common case is an object that loads a Form instance, while the Form instance holds a reference back to the original object for communication (such as bubbling some event). Usually what you need here is a Public method in the Form that the object can call when it receives a Class_Terminate event. In that method you release the back-reference to the parent object.

However from your description it is impossible to say what is going on.

You might look at Dealing with Circular References but you should already be familiar with this material before attempting these sorts of things. The VB6 manuals are full of warnings about it.
 
Thanks for your comments (criticisms). Obviously I am lacking fundamentals here; that is not disputed.

The ActiveX EXE has a Winsock control which is on a form. When it raises the event, it doesn't do anything further - so that's probably why it doesn't die. But I also don't do any Set Object = Nothing in the standard EXE, because I don't know which object to set to Nothing.

Here is the code:

Standard EXE:

Code:
[Form]
Option Explicit
Public WithEvents SUSSocket As BridgeSocket.clsMain

[Module]
Set frmMain.SUSSocket = New BridgeSocket.clsMain
frmMain.SUSSocket.Send "hello"
Exit Function

ActiveX EXE:

Code:
Public Event DataSent(UnitCode As String, UniqueID As String)
Public Event Error(UnitCode As String, UniqueID As String, ErrNum As Long, ErrDesc As String)

Public Sub SendDataToSUS(Data As String)


With frmWsk.wsk
    
    .Close
    
    .Connect
    
    If .State = sckConnected Then
    
        .SendData Data
        
        RaiseEvent DataSent(UnitCode, UniqueID)
        
    Else
    
        RaiseEvent Error(UnitCode, UniqueID, -1, "Could not bring up socket on port " & Port)
        
    End If
        
End With

End Sub

As you can see, at no point in either EXE do I attempt to "release [the] reference" etc.

After sending the data, should I put a "Set frmWsk = Nothing" or something?
 
It is very hard to tell what is going on here. Some of it would depend on things like the instancing set on clsMain and the threading model chosen for the ActiveX EXE Project.


It appears as if you repeatedly call "that function" in "that module" (names might help) and it creates an instance of clsMain hosted in "that Form" and calls its method Send (which doesn't match the method SendDataToSUS that you listed).

Each time this happens, clsMain.Send (or is it SendDataToSUS?) touches the Form frmWsk causing a private global instance of frmWsk to load.

On a subsequent call to "that function" in "that module" you do the same thing all over again. This drops the reference to the current (now previous) instance of clsMain and creates a new one.

In the meantime, the current (now previous) orphaned instance of clsMain cannot terminate because it holds a reference to its private instance of frmWsk which is still loaded and running.


At a bare minimum you'd want to have clsMain do an [tt]Unload frmWsk[/tt]. However the trick is to know when to do it. Winsock.SendData calls are not synchronous and so will not have completed at any point you can guess. This is precisely why Winsock raises a SendComplete event!

This whole application seems very odd. Usually the only reason to use an ActiveX EXE this way is for multithreading, and the way the Winsock control works you don't need multithreading. Weirder yet this seems to be a client, where multithreading is normally of very limited value.

I think your first mistake is using an ActiveX EXE here at all. Beyond that your mistake is repeatedly creating new instances of clsMain and orphaning the old ones. Beyond that your mistake is leaving instances of frmWsk loaded, which prevents orphaned clsMain instances from terminating.


Get rid of the ActiveX EXE, get rid of "that module," and just put a Winsock control on "that form" in your standard EXE and use it there. All done.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top