When designing a component for a distributed application, you have two choices. Your first choice is to use a simple .NET Remoting object (configured as a single-call or client-activated object) or an XML Web service and allow .NET to handle all the details needed to support multiple users. In this case, you don't need to worry about threading at all because .NET automatically creates a separate object instance to serve each client (as shown in Figure 7-1). Your other choice is to create a custom component designed to handle multiple clients. You can host this component in the ASP.NET application state collection so it's available to all XML Web services and Web pages, or you can host it in a .NET Remoting component host (by configuring it with singleton activation). In these cases, you take on the responsibility for handling multiple clients. This means that you create new state objects and threads to serve client requests as needed (as shown in Figure 7-2). This allows your threads to act in more or less the same way they would in a single-client environment. Figure 7-1. Serving multiple clients with a single-call object
Figure 7-2. Serving multiple clients with a singleton object
Clearly, using singleton designs adds complexity. So why would you want to tackle this approach? Here are some possible reasons:
Remember that you pay a price for these features. It's fairly easy to create a simple infrastructure for handling multiple clients with a singleton component. However, it's not easy to create an infrastructure that's as robust and efficient as .NET. For example, ASP.NET processes all XML Web service requests using a pool of worker threads and provides a machine.config configuration file that enables you to tailor details such as how often worker processes are recycled. Duplicating these features is a major programming and testing effort, requiring a dedicated software development team doing little else. In general, a singleton server component is easiest to design if you know in advance that it will always be used in a single, specified manner, for a specified task. This chapter doesn't explain everything you need to know (the threading considerations alone could fill an entire book), but it does give you a solid grounding in the core issues you must consider. |