Q:

Difference between AppDomain, Assembly, Process, and a Thread

What is the difference between AppDomain, Assembly, Process, and a Thread?

A:

An AppDomain is an isolation unit within a process.  AppDomains can be created at runtime, loaded with code, and unloaded.  Its an isolation boundary designed to make .NET apps more reliable.  
An assembly holds one or more modules, which hold compiled chunks of code.  You will typically see an assembly as an .EXE or a .DLL.
A process is an executing application (waaaay oversimplified).
A thread is an execution context.  The operating system executes code within a thread.  The operating system switches between threads, allowing each to execute in turn, thus giving the impression that multiple applications are running at the same time.
To put it all together (very simplified)...
A program is executed.  A process is created by the operating system, and within its single thread it starts loading code to execute.  In a .NET application, a single AppDomain is created by the CLR.  The application's executing assembly (the .EXE) is loaded into this AppDomain and begins execution.  The application can spawn new processes, create AppDomains, load other assemblies into these domains, and then create new Threads to execute code in any of these AppDomains.

A:

One of the biggest advantage of CLR's JIT compiler is - it prevents overlapping of processes' virtual address space. For example, if process 1 is spawned and the CLR (MScorEE.dll) is managing the execution of a managed assembly (.exe or .dll) within that process, then the JIT compiler will make sure that the virtual address space allocated to this process will not collide or overlap with the other adjacent processes. Having this advantage, it is now possible to re-use the single process for more than one managed code execution! Each managed code execution will have its own AppDomain and more than AppDomains could be part of a single process. This is what used by IIS and SQL Server (single process, many AppDomains).
Assembly is an abstract term that represents a single, re-usable component of managed code. Assembly consists of Metadata (PE32 or PE32+ header + IL header) and IL instructions. CLR's JIT compiler compiles and converts ILs of assembly into a machine specific instruction set, based on the processor and it's architecture (x86 or x64).
Process is what OS uses to facilitate the execution of a program. A process is a "RAM representation" of a program that has address space which consists of stack, heap, static and code region. Each process has a unique process Id associated with it.
Thread is a light weight process. A process has at least one thread (i.e. main thread) and depending upon the parallelism OS can create multiple threads within a single process and context-switch among them to support faster program execution. Threads can share some memory regions within a process.

