我试图了解ExecutionContext在.NET Framework 4.0及更高版本中的实际工作原理。文档说当使用Thread.Start和大多数线程池操作时,托管原则,同步,区域设置和用户上下文都流向新线程。但我在实践中看不到这一点。
这是一个简单的控制台应用程序,用于测试启动新线程时同步上下文和托管原则是否流动...
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);
}
结果是......
ThreadRun Id=11 Context=False Principle=One
ThreadRun Id=12 Context=False Principle=Two
因此,同步上下文永远不会流动,并且即使在您指定它时,托管原则也始终会流动。基本上文档是完全错误的。那么是否描述了ExecutionContext在现实中的作用以及它为何有用?
答案 0 :(得分:9)
这是非常误导性的文件。我无法回答你问题的更广泛主旨,但我可以告诉你为什么SynchronizationContext
不会流动。
如果你查看Thread.Start的来源,它最终会调用:
[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);
}
请注意,它默认显式传递ExecutionContext.CaptureOptions.IgnoreSyncCtx
。无论ExecutionContext.SuppressFlow()如何,它都会传递CallContext.Principal
。所以,解释了为什么你看到你所看到的,但不是什么时候它可能有用或为什么文档是错误的!