The series so far:

  1. The Unconventional Guide to Introduction to Thread
  2. Why Do People Think Dedicated CLR Threads is a Good Idea?
  3. How Not Knowing Thread Members and Execution State Makes You a Rookie
  4. Doing Thread Scheduling and Priority the Right Way
  5. How to Start Using CLR's Thread Pool
  6. What Wikipedia Can't Tell You About Thread Execution Contexts
  7. The Insider's Guide to Cooperative Cancellation and Timeout


Every Thread has an execution context data structure associated with it.

The ExecutionContext class provides a single container for all information relevant to a logical thread of execution. This class includes Security context, Call context, and Synchronisation context.

Please refer to the below table.

Security Settings Compressed Stack Windows Identity Thread’s Principal
Host Settings Host Execution Context Manager
Logical Call Context Data System.Runtime.Remoting.Messaging.CallContext.LogicalSetData
Execution Context

Note: The common language runtime ensures that the ExecutionContext is consistently transferred across runtime-defined asynchronous points within the managed process.


Let us examine the default Behavior between a Thread and a Helper Thread. Whenever Thread uses another Thread to perform tasks:

  1. Execution Context flows to the helper thread
  2. Same Security and Host Settings
  3. Data Stored in Logical Call Context available


There is a performance hit due to copying thread context data from the initial thread to a helper thread. We can suppress / restore the flow of thread context data (generally in the I/O Operations) using the ExecutionContext class and its method ExecutionContext.SuppressFlow().
Let's see below example to control Flow of Execution Context in Threadpool.

//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using System.Security.Principal;
using System.Diagnostics;

namespace Rextester
    public class Program
        public static void Main(string[] args)
            //Put some data into the Main’s thread logical context
            CallContext.LogicalSetData("DummyKey", "DummyValue");

            // Create a new instance of the identity class and initialize it with the name you want it to hold
            GenericIdentity MyIdentity = new GenericIdentity("MyUser");  
            // Create a new instance of the GenericPrincipal class and initialize it with the 
            // previously created GenericIdentity object and an array of strings that represent the roles that you want
            // associated with this principal.
            String[] MyStringArray = {"Manager", "Teller"};  
            GenericPrincipal MyPrincipal = new GenericPrincipal(MyIdentity, MyStringArray);
            // Use the following code to attach the principal to the current thread. 
            Thread.CurrentPrincipal = MyPrincipal; 

            // We get data from the Main’s thread logical context
                state =>
                    Trace.WriteLine("The helper’s thread context allowed to copy the main’s thread context");
                    Trace.WriteLine(String.Format("Call context data: {0}", CallContext.LogicalGetData("DummyKey")));
                    Trace.WriteLine(String.Format("Thread.CurrentPrincipal.Identity.Name: {0}", Thread.CurrentPrincipal.Identity.Name));


            //Now, let’s do some optimization and suppress the flow of the Main’s thread execution context

            //So now, since we have suppressed the flow of the Main’s thread execution context, we can’t get any data
                state =>
                    Trace.WriteLine("Suppressed flow");
                    Trace.WriteLine(String.Format("Call context data: {0}", CallContext.LogicalGetData("Key")));
                    Trace.WriteLine(String.Format("Thread.CurrentPrincipal.Identity.Name: {0}", Thread.CurrentPrincipal.Identity.Name));

            //Let’s other threads to get access to the thread logical context


Execution context
How to: Create GenericPrincipal and GenericIdentity Objects