Visual Basic Concepts

Circular References and Component Shutdown

The following procedure shows how Visual Basic unloads an in-process component after the client has released all references to its objects. It also shows how circular references can prevent this unloading, and highlights an important difference between public and private objects.

The procedure can only be run using the compiled component and compiled test project, because Visual Basic never unloads an in-process component project running in the development environment.

Note   This topic is part of a series that walks you through creating a sample ActiveX DLL. It begins with the topic Creating an ActiveX DLL.

To observe DLL unloading

  1. Add a new class module to ThingDemo. Name it TellTale, and set its Instancing property to Private. Add the following code to its Terminate event:

    Private Sub Class_Terminate()
       MsgBox "Private object destroyed"
    End Sub
    

    A private object cannot be created by clients, and should never be passed to them. As you’ll see, private objects do not keep in-process components from unloading, and a client that uses a reference to a private object after its component has unloaded will suffer a catastrophic program failure.

  2. Add the following code to Module1 in ThingDemo:

    Option Explicit
    Private mtt As TellTale      ' New code.
    
    Sub Main
       Debug.Print "Executing Sub Main"
       Set mtt = New TellTale      ' New code.
    End Sub
    

    Once the projects are compiled, Debug statements can’t be used to show what’s happening internally. Like a canary in a coal mine, the TellTale object will give us an indication of what’s happening in the compiled component.

  3. On the File menu, click Make Project Group to compile both ThingDemo and ThingTest. On the Start menu, click Run to open the Run dialog box, and browse to find and run ThingTest — or use the Windows Explorer.

  4. Close the modal dialog box, and click Create Temporary Thing. Enter any name you like in the input box, and click OK.

    As you saw earlier, the temporary Thing doesn’t hang around long. The only reason to create it now is to load ThingDemo.dll and execute Sub Main. For this procedure, the interesting question is what happens when the Things are all gone.

  5. Wait a few minutes. Go get a cup of coffee. You deserve it. When you come back, after a few minutes have elapsed, you’ll see a message box with the message "Private object destroyed."

    What happened? There were no references to public objects, so after a decent interval (usually about two minutes, although this will vary depending on how frequently it gets idle time) Visual Basic will attempt to unload the in-process component.

    When the DLL is unloaded, Visual Basic frees the memory it was using — including variables containing private object references. As a result the TellTale object is destroyed, and you get a visual cue that the DLL has unloaded.

    If you create a new Thing object at this point, you’ll notice a slight pause as the DLL is reloaded.

  6. Now for the circular references. Check the Stuck on itself box, and then click Create Temporary Thing to create a Thing object with a reference to itself.

  7. Wait a few minutes. Go get another cup of coffee. Drink it. Wait a few more minutes. Do some other work. However long you wait, the DLL will not unload, because the reference to the Thing object keeps Visual Basic from unloading it.

    Visual Basic can’t tell the difference between an internal reference to a public object and an external (client) reference to a public object, so it has no choice but to keep the DLL loaded.

  8. Close ThingTest’s main form. The private object is again destroyed, because unloading the client application also unloads any in-process components it’s using.

For More Information   The rules for component shutdown are listed in "Starting and Ending a Component" in "General Principles of Component Design," and discussed in more detail in "ActiveX Component Standards and Guidelines."

Step by Step

This topic is part of a series that walks you through creating a sample ActiveX DLL.

To See
Go to the next step ActiveX DLL Creation Summary
Start from the beginning Creating an ActiveX DLL.