How does .NET ExecutionContext work?

I am trying to figure out how ExecutionContext works in version 4.0 and higher of the .NET Framework. The documentation says that the guided principle, synchronization, locale and user context are passed to the new thread using Thread.Start and most thread pool operations. But I don’t see it working in practice at all.

Here is a simple console application that verifies that the synchronization thread and the guided flow principle when starting a new thread ...

static void Main(string[] args) { SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("One"), null); Thread t1 = new Thread(new ThreadStart(ThreadRun)); t1.Start(); t1.Join(); SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Two"), null); AsyncFlowControl aFC = ExecutionContext.SuppressFlow(); Thread t2 = new Thread(new ThreadStart(ThreadRun)); t2.Start(); t2.Join(); aFC.Undo(); Console.Read(); } static void ThreadRun() { Console.WriteLine("ThreadRun Id={0} Context={1} Principle={2}", Thread.CurrentThread.ManagedThreadId, (SynchronizationContext.Current != null), Thread.CurrentPrincipal.Identity.Name); } 

Result...

  ThreadRun Id=11 Context=False Principle=One ThreadRun Id=12 Context=False Principle=Two 

Thus, the synchronization context never flows, and the guided principle always flows, even if you do not specify it. Basically the documentation is completely incorrect. So, is there a description of what ExecutionContext actually does and why is it useful?

+6
source share
1 answer

This is pretty misleading documentation. I cannot answer the broader question of your question, but I can tell you why the SynchronizationContext does not flow.

If you look at the source of Thread.Start , it eventually calls:

  [SecuritySafeCritical] private void Start(ref StackCrawlMark stackMark) { this.StartupSetApartmentStateInternal(); if (this.m_Delegate != null) ((ThreadHelper) this.m_Delegate.Target).SetExecutionContextHelper(ExecutionContext.Capture(ref stackMark, ExecutionContext.CaptureOptions.IgnoreSyncCtx)); this.StartInternal(CallContext.Principal, ref stackMark); } 

Note that it explicitly passes ExecutionContext.CaptureOptions.IgnoreSyncCtx by default. It also passes CallContext.Principal regardless of ExecutionContext.SuppressFlow (). So, it explains why you see what you see, but not when it can be useful or why documents are flat wrong!

+8
source

Source: https://habr.com/ru/post/911371/


All Articles