Activation Models and Synchronization
In a distributed application, the hosting domain registers the objects with .NET that it is willing to expose as well as their activation modes. Each incoming client call into the host is serviced on a separate thread from the thread pool. That allows the host to serve remote client calls concurrently and maximize throughput. The question is, what effect does this have on the object synchronization requirements?
Client-activated objects and synchronization
When it comes to synchronization, client-activated objects work like classic client-server objects. If multiple clients share a reference to an object, and the clients can issue calls on multiple threads at the same time, then you must provide for synchronization to avoid corrupting the state of the object. It would be best if the locking were encapsulated in the component itself either by using synchronization domains or by using manual synchronization. The reason is clear: Any client-side locking (such as using the lock
statement) will only lock the proxy, not the object itself. Another noteworthy point is thread affinitybecause each incoming call can be on a different thread, the client-activated object should not make any assumption about the thread it is running on, and avoid mechanisms such as thread-relative static or thread local storage. This is true even if the object is always accessed by the same client, and that client runs always on the same thread.
Single-call objects and synchronization
In the case of a single-call object, object-state synchronization is not a problem because the object's state in memory exists only for the duration of that call and cannot be corrupted by other clients. However, synchronization is required when the objects store state between method calls. If you use a database then you have to explicitly lock the tables, or you can use transactions with the appropriate isolation level to lock the data. If you are using the file system then you need to prevent sharing the files you access while a call is in progress.
Singleton objects and synchronization
Unlike client-activated objects, the clients of a singleton object may not even be aware that they are sharing the same object, and may not take the necessary precautions to lock the object before access. As a result, you should enforce synchronization of a singleton object on the object side. You can use either synchronization domain or manual synchronization. Similar to a client-activated object, a singleton object must avoid thread-affinity.
Distributed applications have come a long way from the days of simple client-server over the wire. Developing modern distributed applications requires taking into account the scalability and throughput needs, and selecting the appropriate object model. In the past, programming models such as single-call objects required application server platforms such as COM+. .NET remoting natively offers developers a range of programming models that take into account the scalability and performance needs of the application, thus significantly simplifying the overall programming model. As long as your objects comply with the design guidelines of the respective object models described in this article, you should be well on your way to successfully developing and deploying a distributed .NET application. (See Sidebar: COM Singleton)