Visual Basic Concepts
Your component starts the first time a client application requests an object from one of your classes. A new instance of the class is created, and the client receives a reference to the newly created object.
If your component has a Sub Main procedure, it will execute when the first object is requested. The object will not be created until Sub Main has finished.
Important Don’t execute lengthy initialization activities in Sub Main, as this may cause object creation to time out and fail.
You should not show forms or user messages from your Sub Main, because they can cause the same problems as lengthy initialization tasks. Visual Basic does not allow forms as start up objects in ActiveX EXE and ActiveX DLL projects, for precisely this reason.
A desktop application that provides objects should test App.StartMode, and show its main form only if it was started standalone. In this case, Sub Main may happen long before the first object is requested.
Note If you have selected ActiveX Component for the Start Mode option, on the Component tab of the Project Properties dialog box, Sub Main will not execute immediately when you put your component into run mode. Visual Basic does this to allow accurate debugging of your startup code. Once your component is compiled, Sub Main will not execute until the first time a client requests an object, so the development environment exactly duplicates this behavior.
You can perform initialization in the Class_Initialize event of the first object created. When initialization is complete, set a global flag so that subsequent instances of the class don’t execute the initialization task.
Alternatively, you can defer some initialization tasks until the service is actually needed. In this case, each object must test before using the service, to ensure it has been initialized — and to initialize it if it has not. This technique works best when initialization consists of many small, independent tasks.
A very large initialization task that cannot be broken up can be performed in the background, using a call-back timer. You can start the timer at the end of Sub Main, as discussed in "Building Code Components." In the timer’s Tick event, disable the timer and run the lengthy task. At the end of the Tick event, set a global flag to indicate that the component is initialized. You can then notify any objects that have been created while initialization was in progress.
Important Don’t use a Timer control for this purpose, because the Timer control requires a form to be loaded.
When you use this technique, make sure each object tests the global flag during its own Initialize event. If the component is not initialized, each object should insert itself into a global collection, so it can be notified when background initialization is complete.
You can add a notification method — for example NotifyInitComplete — to each class. Make this a Friend method, so it’s only visible within your component.
For More Information Friend methods are discussed in "Private Communications Between Your Objects," later in this chapter.
Your component should shut down when all clients have released all references to the objects the component provides. (A desktop application that provides objects is an exception to this rule.)
Visual Basic does a number of things to make it easy for your component to shut down properly. The most important of these is keeping track of references to your public objects, because your component should never close while clients still hold references to objects.
Important Only references to public objects will keep a component running. References to private objects — objects provided by Visual Basic, or objects from classes marked Private — will not prevent component shutdown and subsequent catastrophic failure of the client. References to private objects should never be passed to clients.
The rules Visual Basic uses to determine when to shut down are different for in-process and out-of-process components.
An out-of-process component written with Visual Basic will shut down when:
A loaded form will keep your component running past the point at which all references have been released. Forms should be unloaded when the object that created them terminates.
Internal references to public objects will not keep a component running if clients have released all their references. Neither will references held by an in-process component the out-of-process component is using.
In the long run, the lifetime of an in-process component is controlled by its client, because the component runs in the client’s process. When the client closes, the component is unloaded regardless of any outstanding object references, open forms, and so on.
A client may ask an in-process component to unload when the client is no longer using objects the component provides. The following rules describe the way a Visual Basic in-process component determines whether it should unload in response to a client request.
A visible form will keep your component in memory, even if there are no object references; an invisible form will not.
If your in-process component is holding a reference to one of its own public objects, Visual Basic will not unload it. Visual Basic cannot tell whether the reference is internal or external.
Note A client application written in Visual Basic may not attempt to unload an in-process component immediately after the last reference is released. The frequency of attempts depends on how frequently idle time becomes available; in general it will be around two minutes.
For More Information A more complete discussion of the rules for component shutdown can be found in "ActiveX Component Shutdown" in "ActiveX Component Standards and Guidelines."