In the preceding example, we made the assumption that throughout the life of the client application (that is, from start-up to shut-down), the application holds connections to three different types and at least three instances of business objects. So if we have 50 client applications running on desktop PCs, we have at least 150 instances of server-side business objects.
The counting instances aspect depends partly on whether an object can be used by more than one user at a time. In Visual Basic 4 and Visual Basic 5, you can specify this by setting the class’s Instancing property, as shown in Figure 2-4.
Figure 2-4 Setting a class’s Instancing property inVisual Basic 5
SingleUse Creatable If you picked 3 - Single-Use, each client essentially got its own copy of the object. When the client application set its object reference to nothing, it closed down if nothing else was holding a reference to that server object instance since the OLE method is based on instance count, much like old-style DLLs.
MultiUse Creatable If you set the class’s Instancing property to 5 - MultiUse, you could have multiple client applications accessing one object. When a client application tries to create an instance of that class, it will first check to see whether there is already a running copy of the code; if there is, that code will supply the object. Excellent, dude! Only what about the data? If you’ve got two client applications running a single process, what about your global data? Who’s seeing what? If one client changes the data, how is the other client’s data affected? Well, we’re safe, more or less. What we have is a separate copy of global data per thread. If your objects are on different threads, even if they are created in the same loaded code (as in a MultiUse instanced server’s EXEs), they get their own copy of global data. If they are SingleUse EXEs, every client calling in to the top-level class loads a new instance of the code, and therefore the data (that is, what fills its properties) is obviously unique. If your objects are DLLs, they haven’t got a thread of their own but are created on another process’s thread, so you have more than one object on a thread. There is one risk, though. If you were to create a multithreaded EXE with a MultiUse instancing in its top-level class and use a thread pool to give round-robin creation to your threads (see the “Multiple threads of execution” section below), you could get two objects created on one thread with one copy of global data. You can’t predict which thread an object will go on in this scenario unless you set the thread pool to 1.
Hang on though, we just said that MultiUse instanced objects have only one set of loaded code! Warning bells, alarms, dive, dive, dive! So this means that when client A calls in and wants to execute a long-running method at the same time client B calls in and wants to execute some method, the request that came to the server first is serviced and the second is blocked. This happens because there is only one set of loaded code; and since Visual Basic 5 is by default—as it is in Visual Basic 4—single threaded, only one process can run at a time. You have just been torpedoed by serialization and single-threadedness in Visual Basic 5, and the U.S.S. Scalability has gone down with all hands again.
So MultiUse Creatable looks like bad news when you’re trying to build a scalable client/server system.