By introducing a layer between the program and the operating system, it is possible to implement virtual processes or applications known as application domains (app domains). An application domain behaves like an operating system process in that it offers a level of isolation between other application domains. For example, an app domain has its own virtual memory allocation, and communication between application domains requires distributed communication paradigms, just as it would between two operating system processes. Similarly, static data is not shared between application domains, so static constructors run for each application domain, and assuming a single thread per application domain, there is no need to synchronize the static data because each application has its own instance of the data. Furthermore, each application domain has its own threads, and just like with an operating system process, threads cannot cross application domain boundaries.
The point of an application domain is that operating systems are considered relatively expensive. With application domains, you can avoid this additional expense by running multiple application domains within a single process. For example, you can use a single process to host a series of web sites. However, you can isolate the web sites from each other by placing them in their own application domain. In summary, application domains represent a virtual process on a layer between an operating system process and the threads.