2012-03-22 124 views
6

我想了解ExecutionContext实际上在.NET Framework 4.0及更高版本中的工作原理。该文档指出,在使用Thread.Start和大多数线程池操作时,托管原则,同步,语言环境和用户上下文都将流向新线程。但在实践中我看不到这一点。.NET ExecutionContext如何实际工作?

这里是如果同步内容和管理原则流开始一个新的线程时测试一个简单的控制台应用程序...

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在现实中做什么的描述以及它为什么有用?

回答

8

这是非常具有误导性的文档。我无法回答你的问题的更广泛的主旨,但我可以告诉你为什么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。因此,解释了为什么你看到了你所看到的内容,但不是什么时候它可能有用,或者为什么这些文档是错误的!