Programming .NET Components : Remoting - Application Domains (part 1)

8/8/2012 6:14:30 PM
All .NET components and applications require a managed environment to run in. However, the underlying operating system knows nothing about managed code; it provides processes only. Processes are also unaware that .NET exists; they provide raw elements such as memory, handle tables, and so on. Managed code therefore can't execute directly in the native operating system process—there is a need for a bridge between managed code and unmanaged code. The bridging link is a concept called an application domain, or app domain. You can think of the app domain as the .NET equivalent of a process, with one important difference: an app domain is built on top of the unmanaged process, and there is no requirement for one-to-one mapping between app domains and operating system processes. As a result, a single physical process can actually host multiple app domains (see Figure 1).
Figure 1. Processes, app domains, and assemblies

1. App Domains Versus Physical Processes

App domains are better perceived as logical processes, instead of real processes. The fact that a single physical process can host multiple app domains yields important benefits. The main reason why developers resorted to multiple processes in the past was to provide fault isolation. If all the components of an application and their clients are in the same process and a component has a fatal error that crashes the process, it brings down the entire application, including the clients. Similarly, if the client has a fatal error, the components go down with it. By distributing the clients and servers of an application to separate processes, an application achieves fault isolation—in the event of a fault only the culprit process goes down, allowing you to handle the error or perform a graceful exit.

Another reason for distributing the components of an application across processes is security. Server objects are often called on to authenticate incoming client calls or to perform access control and authorization before allowing a given call to access a component. Having separate processes allows for separate security identifiers for each process and for the enforcement of authentication on cross-process calls. Unfortunately, however, there are significant penalties to using multiple processes:

  • Creating a new process is time-consuming, as is the disposal of an existing process.

  • Keeping a process running is expensive, both in terms of memory and of the resources the operating system allocates to each process. Having too many processes running can significantly degrade system performance.

  • Making a cross-process call involves a call penalty, because crossing a process boundary is very expensive compared to making a direct call. Cross-process calls rely on special mechanisms such as named pipes, sockets, and LPC/RPC.

  • Coding is more complex—the client's code for making a direct local call on an object is very different from that of making the same call on the object in a different process.

Compared with traditional unmanaged processes, .NET app domains can provide single-process performance with lower overhead. They can also provide the isolation and other benefits of multiple processes, even if they share the same physical process. You can start and shut down app domains independently of their hosting processes, and you can even debug them separately. For example, all ASP.NET web applications share the same physical worker process by default, but each web application is put in its own dedicated app domain. The time it takes to create or destroy an app domain is a fraction of that required for a physical process, and keeping an app domain alive is considerably cheaper. Furthermore, cross-app domain calls in the same process are faster than cross-process calls. .NET also maintains a strict security boundary between app domains, so objects in one app domain can't interfere with the objects (or data) in another, unless the objects agree to cooperate using .NET remoting.

In unmanaged C++, static variables are visible to all clients in the same process. In C#, each app domain gets its own separate set of static variables.

In the interest of fault isolation and security, each app domain loads and maintains its own set of assemblies. Consider, for example, the app domains in Figure 10-1. Because App Domain B and App Domain C require the class library Assembly 1, on Windows .NET loads Assembly 1 twice and gives each app domain its own copy. This allows clients in each app domain to interact with Assembly 1 independently of other clients in other app domains.

2. App Domains and the .NET Platform

The .NET runtime itself is a set of Windows DLLs, implemented in unmanaged C++. These DLLs provide the managed heap, garbage collector, JIT compiler, assembly resolver and loader, and all the other elements that make managed code possible. The app domain merely enables the assemblies it loads to access these services (see Figure 2)—in effect, this is how the app domain bridges the unmanaged world and the managed world. However, it's important to note that all app domains in the same process share the same managed heap.

Figure 2. App domains provide their assemblies with access to the .NET runtime services

2.1. App domains and threads

.NET managed threads have no app domain affinity, meaning that a thread can enter and exit any app domain that runs in the same underlying process. Typically, when you create a thread in your app domain, that thread executes a thread method and accesses only local objects. However, nothing prevents you from having threads created in one app domain access objects in another app domain in the same process. There is one detail you need to be aware of, though: when an app domain shuts down (i.e., when AppDomain.Unload( ) is called), it terminates all the threads that happen to be calling objects in it by calling Thread.Abort( ) on each of them.

3. App Domains and Remoting

Like traditional cross-process calls, you make cross-app domain calls using remoting, a programmatic act that accesses an object outside its hosting app domain. .NET uses exactly the same remote-call architecture for all cases, whether the cross-app domain call is between two app domains in the same process, between app domains in two different processes on the same machine, or between app domains on two separate machines (see Figure 3).

Figure 3. All cross-app domain calls use remoting

Clients in the same app domain as the called object can each have a direct reference to the object (see Figure 3). Clients in a different app domain use a proxy to connect to the object. A proxy is an object that provides exactly the same interfaces, public methods, properties, and members as the real object. .NET generates the proxy on the fly, based on the object's metadata. Even though the proxy has the same public entry points as the object, it can't serve the clients because the object's actual code and state reside only where the object is. All the proxy knows is how to bind to the object and forward the calls made on the proxy to the object. Forwarding a call to an object is called marshaling. Marshaling is a nontrivial feat: its end goal is to provide the client with the illusion that it's calling a local object and to provide the server with the illusion that it's servicing a local client. Neither the server nor the client explicitly uses remote mechanisms such as pipes, RPC, or sockets, because these details are encapsulated in the proxy. .NET does require, however, that if an object is accessed by proxy, the object's class must derive directly or indirectly from the abstract class MarshalByRefObject.

  •  BizTalk 2006 : Managing Exceptions in Orchestrations (part 4) - Processing and Retrieving Messages and Exceptions from the Fault Message
  •  BizTalk 2006 : Managing Exceptions in Orchestrations (part 3) - Running the EAIProcess
  •  BizTalk 2006 : Managing Exceptions in Orchestrations (part 2) - Failed Orchestration Routing API for BizTalk 2006
  •  BizTalk 2006 : Managing Exceptions in Orchestrations (part 1) - The Exception Management Challenge
  •  D-Link DHP-1565 Wireless N Powerline Router
  •  Application Patterns and Tips : Localize a Windows Forms Application, Localize an ASP.NET Application
  •  Application Patterns and Tips : Use Model-View-ViewModel in WPF
  •  Liquid-Metal
  •  Vigor 2850n
  •  Visual Studio 2010 : Introducing the Visual Studio Extensibility - Extending the Code Editor
  •  Visual Studio 2010 : Managing Extensions with the Extension Manager, Managing Add-Ins with the Add-In Manager
  •  Intel Xeon Phi: Coprocessor speeding at 1 teraflops in a PCIe Card
  •  Visual Studio Team System 2008 : Working with Test Results (part 2) - Build report and test result
  •  Visual Studio Team System 2008 : Working with Test Results (part 1) - Test as part of Team Foundation Server build
  •  Finance - Apple Versus Google
  •  Oracle Coherence 3.5 : Testing and debugging Coherence applications
  •  Oracle Coherence 3.5 : Accessing the data grid (part 6) - Using the Coherence API - Implementing CoherenceTarget, Testing the Cache loader
  •  Oracle Coherence 3.5 : Accessing the data grid (part 5) - Using the Coherence API - Loader design, Implementing CsvSource
  •  Oracle Coherence 3.5 : Accessing the data grid (part 4) - Using the Coherence API - The basics: NamedCache and CacheFactory
  •  Oracle Coherence 3.5 : Accessing the data grid (part 3) - Configuring Coherence
    Top 10
    Nikon 1 J2 With Stylish Design And Dependable Image And Video Quality
    Canon Powershot D20 - Super-Durable Waterproof Camera
    Fujifilm Finepix F800EXR – Another Excellent EXR
    Sony NEX-6 – The Best Compact Camera
    Teufel Cubycon 2 – An Excellent All-In-One For Films
    Dell S2740L - A Beautifully Crafted 27-inch IPS Monitor
    Philips 55PFL6007T With Fantastic Picture Quality
    Philips Gioco 278G4 – An Excellent 27-inch Screen
    Sony VPL-HW50ES – Sony’s Best Home Cinema Projector
    Windows Vista : Installing and Running Applications - Launching Applications
    Most View
    Bamboo Splash - Powerful Specs And Friendly Interface
    Powered By Windows (Part 2) - Toshiba Satellite U840 Series, Philips E248C3 MODA Lightframe Monitor & HP Envy Spectre 14
    MSI X79A-GD65 8D - Power without the Cost
    Canon EOS M With Wonderful Touchscreen Interface (Part 1)
    Windows Server 2003 : Building an Active Directory Structure (part 1) - The First Domain
    Personalize Your iPhone Case
    Speed ​​up browsing with a faster DNS
    Using and Configuring Public Folder Sharing
    Extending the Real-Time Communications Functionality of Exchange Server 2007 : Installing OCS 2007 (part 1)
    Google, privacy & you (Part 1)
    iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
    Microsoft Surface With Windows RT - Truly A Unique Tablet
    Network Configuration & Troubleshooting (Part 1)
    Panasonic Lumix GH3 – The Fastest Touchscreen-Camera (Part 2)
    Programming Microsoft SQL Server 2005 : FOR XML Commands (part 3) - OPENXML Enhancements in SQL Server 2005
    Exchange Server 2010 : Track Exchange Performance (part 2) - Test the Performance Limitations in a Lab
    Extra Network Hardware Round-Up (Part 2) - NAS Drives, Media Center Extenders & Games Consoles
    Windows Server 2003 : Planning a Host Name Resolution Strategy - Understanding Name Resolution Requirements
    Google’s Data Liberation Front (Part 2)
    Datacolor SpyderLensCal (Part 1)