Megosztás a következőn keresztül:


Visual Basic Concepts

Scalability Through Multiple Processes: SingleUse Objects

Visual Basic provides a second mechanism for using multiple threads of execution. By setting the Instancing property of a class to SingleUse, you cause each instance of the class to run in a separate instance of your component. This means that even though your component is single-threaded, each instance of the SingleUse class has its own thread of execution.

SingleUse objects require a lot more overhead than multiple objects in a multithreaded component. However, there are several reasons you might want to use SingleUse objects:

  • If your component must show forms, active documents, or other user interface elements, you cannot mark it for unattended execution — and thus it cannot be multithreaded. Components that provide SingleUse objects can have forms and active documents.

  • Your component can function as a standalone desktop application, and you want it to have an Application object that’s not shared between clients.

  • High-risk activities can be isolated in separate processes with SingleUse objects. If the object suffers a fatal error, other processes are not affected. By contrast, a fatal error in a multithreaded component terminates all threads.

Using Createable SingleUse Objects to Avoid Blocking

Figure 8.9 shows how SingleUse objects have separate threads of execution, which can be preemptively multitasked.

Figure 8.9   A component with a SingleUse object

Components That Provide Multiple SingleUse Classes

The best way to provide exclusive use of an out-of-process component is to give it exactly one SingleUse class, with as many dependent objects as necessary.

If you set the Instancing property to SingleUse for more than one class module in your component, satisfying client requests for objects becomes somewhat complicated, and it becomes difficult to ensure that a client has objects from only one instance of the component.

You can think of each class as a hole, which will be filled when an object of that class is created. Figure 8.10 shows a component that provides three objects — Widget, Gear, and Sprocket. Each instance of the component can provide one object of each type.

Figure 8.10   Instancing with three classes marked SingleUse

The lettered rectangles represent the potential to satisfy a request for an object of one of the three classes. A dotted outline indicates that the component has provided an object of that type, and so cannot provide another.

If Client A now creates a Sprocket object, that object will not be supplied by the same instance of the component that provided its Widget object. If the point of making the classes SingleUse was to make it possible for one client to have exclusive use of one component, this scheme will not guarantee it.

As noted above, a better way to accomplish exclusive use of an out-of-process component is to provide one SingleUse object as the only externally creatable object, and as many dependent objects as you need.

No Way to Predict Which Instance Provides an Object

It might appear from Figure 8.10 that Client B has one object from each of two instances of the component because of the order in which it created the objects. However, even if Client B had created its Widget object first, so that the second instance of the component was already running when Client B requested a Sprocket, there’s no guarantee that the Sprocket would be provided by the second instance of the component.

As noted in the callout for Client C, when there are multiple instances of a component that could provide a particular object, the ActiveX specification does not guarantee which instance will provide the object. It’s best to assume random selection.

Internal and External Instancing of SingleUse Classes

When a client creates two instances of a class marked SingleUse, two instances of the component executable are started. Within the component, however, it’s possible to create multiple instances of such a class. Figure 8.11 shows the distinction between internal and external object creation.

Figure 8.11   Internal and external creation of SingleUse objects

When code within the component creates an object from one of the component’s own SingleUse classes using the Set statement with the New operator, or by declaring a variable As New, the object does not fill the ‘hole’ that allows a client to create an instance of the class. Code within the component in Figure 8.11 could create any number of Sprocket objects in this fashion.

When the CreateObject function is used to create an object from a SingleUse class, however, it is as if the object had been created by a client. If the client in Figure 8.11 now attempts to create a Sprocket object, a second instance of the component will have to be started. Another instance of the component will also be started if the component instance in Figure 8.11 uses CreateObject to create another Sprocket.

SingleUse Really Means SingleUse

Once a client application creates an object from a SingleUse class, no client can ever create an object of that class from that instance of the component, even if the first client releases the object. That is, once the ‘hole’ has been filled, it can never be empty — even if the object is destroyed.

In other words, marking a class module SingleUse means that during the lifetime of an instance of the component, only one instance of the class can be created externally — either by a client application, or by the component itself using the CreateObject function.

Debugging Limitations

When you run your component in the development environment, your client test programs can create only one instance of each SingleUse class during that debugging session. Once an instance of a class has been created, subsequent attempts to create an object from that class will cause Error 429, "OLE Automation server can’t create object."

For debugging purposes, you can change SingleUse to MultiUse. However, to test the SingleUse behavior of your component, you must make the component executable.

For More Information   To run your component alternately as an executable file and in the Visual Basic development environment, see "How to Test Compiled Components" in "Debugging, Testing, and Deploying Components."