Inside .NET world and from a purist perspective, application domains can be considered as logical units that allow running multiple assemblies in the scope of single process while preventing them from directly accessing the memory from other assemblies. In this line AppDomains exhibits similar process-philosophy because it provides process-like characteristics like separate memory spaces and discriminated access to resources. It´s said that NET Framework manages AppDomains while the SO manages process.
However AppDomains are in fact more versatile than processes because they offer some useful features that are not feasible from process side. For instance you can download the appDomain in case of any fault or issue, freeing the related resources without having to kill the process.
So AppDomains provide a mean for avoiding creating new processes for doing tasks which save us from the performance overhead due to process-switching.
Said that, we can summarize the first two benefits:
- Reliability: We can use AppDomains to isolate tasks that can cause the main process crash, preserving the healthy state of the process and blocking access to core resources
- Efficiency: We can unload assemblies from memory while the process is running which can be a good solution for freeing resources and minimizing workload in long-time operations
Sharing Data & Security
Common ways for sharing data across app-domains boundaries are remoting or via serialization (in fact by using marshalling by value and by reference by using proxy).
Another important aspect related with AppDomains is that you can define your security policies for each of them which can be useful when we need to load a specific plug-in with security restrictions — in fact this is the recommended way to load third party plugins –, thus you can restrict the permissions for your AppDomain reducing the risk that a third party assembly can cause damage as a result of a malicious action (this is an example of defense-in-depht)
Application domains are managed by using the System.AppDomain class, this class provides two main methods: CreateDomain () (which enables us to create a new AppDomain) and an overload set of the ExecuteAssemby () method for loading assemblies into it
AppDomains & Threads
According to microsoft documentation there is no one-to-one relation between application domains and threads, zero, one or multiple threads can be executed in any give application domain and on the other hand one thread can execute code from different application domains, however the CLR records the track of which threads are running in which application domains, It´s possible find the current application domain in which the thread is executed on by using the Thread.GetDomain method
Far from the explicit use of AppDomains as isolation unit for security, etc.. there is an established relation between the application domains and assemblies by the way the runtime host load one assembly. According to Microsoft documentation, the way in which an assembly is loaded determines whether its JIT (just-in-time) compiled code can be shared by more than one application domain inside a process and how the assembly can be downloaded from it. More specifically an assembly can be loaded as domain-neutral (in which case all applications domains that belongs to the same security grant set can share the same JIT-compiled code which reduces the memory required but make imposible to download the assembly without kill the process).
On the other hand, if the assembly is loaded by the host runtime as not-domain-neutral then the assembly code must be JIT-compiled by every application domain which make possible to download the assembly without killing the process and provide all the previously mentioned isolation features that contribute to efficiency and reliability. As a consecuence, JIT—compiled code can not be shared from assemblies that have been loaded by using the Assembly.LoadFrom() method