Processes, Threads, AppDomains And Object Contexts

Source Code

All source code can be found on GitHub here.

This is part of my HowTo in .NET seriies. An overview can be seen here,


Processes, Threads, AppDomains And Object Contexts

Source Code

All source code can be found on GitHub here.

This is part of my HowTo in .NET seriies. An overview can be seen here,

Processes

Any code executing on a windows platform is wrapped up in a process.

Each process is given a unique PID which can be seen within the Task Manager.

If the code entity being run is determined to be a .NET assembly, an instance of the CLR is created to run the assembly.

Each instance of the CLR receives its own managed heap.

Prior to .NET V4 a process could only host one instance of the CLR. Though this has now been changed, each instance of the CLR still receives its own instance of a managed heap memory allocation.

Each .NET process is run in isolation from other processes; they cannot access each other’s resources such as memory. The separation means that if one process errors it does not bring down other running processes.

Querying Running Processes

The Process class provides a number of static methods for retrieving running processes on either a local or remote computer.

Get all locally running processes on a local machine:

Process[] pids = Process.GetProcesses();

Get all instances of a running application by its name:

Process [] pids = Process.GetProcessesByName("MyApp");

Get all instances of a running application on a remote machine either by the machine name or by IP address:

Process [] pids = Process.GetProcessesByName("MyApp", "Server");

Process [] pids = Process.GetProcessesByName("MyApp", "1.2.3.4");

Get a process by its process id:

Process aProcess = Process.GetProcessById(123);

Retrieve the process name of a retrieved Process instance:

var aName = aProcess.ProcessName;

Starting & Killing Processes

A process can be killed by simply calling Kill on the process instance:

aProcess.Kill ();

The Process class offers the static Start method to start a process by an executable name.

Process.Start("AnApp.exe");

Command line parameters can be passed to the application:

Process.Start("AnApp.exe", "parameter");

Process can take a number of configurations:

Process.Start (new ProcessStartInfo ("AnApp.exe", "AParameter") {
    CreateNoWindow = true,
    WorkingDirectory = @"c:\"
});

Threads

A thread is the smallest sequence of instructions that can be independently managed by an operating system and therefore processed by a processor.

Before the luxury of multi core systems only one thread could be executed at a time. Multiple threads would have to share processor time. Concurrent thread execution would seemingly be achieved by continuously pausing and resuming each running thread on the system.

In todays world of multi core systems multiple threads can genuinely run simultaneously, however seeing as there can be more threads than processors, the same principle holds true.

With multiple threads running on a computer, the processor will give more processor time to threads marked as having a higher priority.

When a Process is started, a default thread is created or spawned which will execute the code associated with the assembly.

Each thread receives it’s call stack; all local variables are placed on the stack and as such are private to the thread.

Thread Members

Code can get access to the thread that is running it with the CurrentThread property:

var aThread = Thread.CurrentThread;

Access to all threads running within a process via the Threads property of a Process instance:

var threads = Process.GetProcesses () [0].Threads;

Determine if the thread is still alive; that it has been started and has not terminated normally or aborted:

var isAlive = aThread.IsAlive;

The name of the thread can be set and retrieved with the name property. This can be helpful to identify which thread is which; the name is shown within the Threads debug window:

aThread.Name = "Thready McFreddy";
var aName = aThread.Name;

Foreground & Background Threads

The CLR has the concept of foreground and background threads.

Foreground Threads can prevent the CLR terminating or unloading an AppDomain.

Background threads can not prevent the CLR from terminating.

A thread can be switched between foreground and background with the IsBackground property:

aThread.IsBackground = true;

Thread Priority

A thread’s priority can be changed to request more or less processing time from the CLR. The higher the priority the more time a thread will be given from a processor. The default priority is normal:

* Lowest
* BelowNormal
* Normal
* AboveNormal
* Highest

To get a threads priority:

var priority = aThread.Priority;

The thread priority can be changed at any point in the threads existence.

aThread.Priority = ThreadPriority.Highest;

Thread State

The state of a thread can be determined via the ThreadState property which returns a member of the ThreadState enum:

var threadState = aThread.ThreadState;

Name

Description

Aborted

The thread has been aborted or requested to be aborted . The thread is dead however its status has not changed to stopped.

AbortRequested

The thread has been requested to abort by Thread.Abort method but it has not received the System.Threading.ThreadAbortException which will terminate it.

Background

The thread is a background thread.

Running

The thread is running, is not blocked and no attempt to terminate has been made.

Stopped

The thread has been completely terminated or stopped.

StopRequested

A request to stop the thread has been made.

Suspended

The thread is suspended.

SuspendRequested

A request to suspend the thread has been made.

Unstarted

The thread has not been started via the Thread.Start method.

WaitSleepJoin

The thread is paused due to either a Thread.Sleep or because a request to get exclusive access to a locked region has been made.

 

Thread Abort

Thread.Abort can be used to stop an executing thread. It will cause a ThreadAbort-Exception to be thrown. Caution should be used when calling this method as it can leave a thread and it’s data in a corrupt state.

Application Domains

An application domain is a segmentation within a process; it provides a level of isolation and security within each process.

AppDomains abstract the OS from the executing code.

Threads are actually associated with a single AppDomain and not a Process.

The CLR creates a default AppDomain and its default Thread as part of executing a .NET assembly.

A Process can contain multiple AppDomains and AppDomains can contain multiple Threads; however these will only exist if if they are created manually by executing code within the Process.

AppDomains are less expensive than Processes; the CLR can load or unload AppDomains quicker than a processes can be created or destroyed.

When an Assembly is loaded it is loaded into an AppDomain. Code within an assembly can only be executed within the AppDomain it was loaded into.

A thread can only run inside one AppDomain at a time though it can be moved between AppDomains when it is seen fit by the CLR, this is to allow thread reuse. A thread can only execute code associated to the AppDomain it is currently running in.

AppDomain Members

Executing code can get access to the domain it is running in via the CurrentDomain property:

AppDomain aAppDomain = AppDomain.CurrentDomain;

An AppDomain instance exposes properties describing itself:

var id = aAppDomain.Id;

var name = aAppDomain.FriendlyName;

var isDefault = aAppDomain.IsDefaultAppDomain ();

var dir = aAppDomain.BaseDirectory;

GetAssemblies lists all .NET assemblies which an AppDomain has loaded into it:

Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies (););

Creating & Loading AppDomains

AppDomains can be created:

var aDomain = AppDomain.CreateDomain("MyDomain");

Loading and executing assemblies into AppDomains:

AppDomain.Load ("Foo");

AppDomain.ExecuteAssembly ("Foo.exe");

An AppDomain allows subscribing to the AssemblyLoad event which is triggered when an assembly is loaded into it:

aaAppDomain.AssemblyLoad += (o, s) => {
            };

Unloading AppDomains

Individual assemblies can not be unloaded though AppDomains can:

AppDomain.Unload(aAppDomain);

An AppDomain allows subscribing to the DomainUnload event which is triggered when it is being unloaded:

aAppDomain.DomainUnload += (o, s) => { };

Process.ProcessExit event is triggered when the Process is exited:

aAppDomain.ProcessExit += (o, s) =>   { };

Object Context Boundaries

An AppDomain splits itself into contexts. The CLR groups types into groups depending upon their context needs.

Most types are placed into the default context; this is referred to as context 0 and the objects contained within as context-agile objects.

CLR creates new contexts when a loaded type requires a new context boundary. Objects requiring thread synchronization typically require this process. This is covered in the the multithreading section.

Creating a Context Bound Object

Objects requiring special context needs must derive from System.ContextBoundObject base.

public class ContextBoundObjectExample : ContextBoundObject
{
}

Inspecting An Object’s Context

var context = Thread.CurrentContext;

var contextId = context.ContextID;

var contextProperties = context .ContextProperties;

var propname = contextProperties[0].Name;
Advertisements

3 thoughts on “Processes, Threads, AppDomains And Object Contexts

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s