2012-03-22 12 views
6

Próbuję dowiedzieć się, jak ExecutionContext faktycznie działa w wersji 4.0 i nowszej .NET Framework. Dokumentacja mówi, że zarządzana zasada, synchronizacja, ustawienia regionalne i kontekst użytkownika przepływają do nowego wątku podczas korzystania z operacji Thread.Start i większości wątków. Ale nie widzę w praktyce, żeby to działało.Jak działa .NET ExecutionContext?

Oto prosta aplikacja, która sprawdza, czy konsola kontekst synchronizacji i zarządzania przepływem zasada, gdy zaczyna się nowy wątek ...

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); 
    } 

Rezultatem jest ...

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

Tak Kontekst synchronizacji nigdy nie przepływa, a zasada zarządzana zawsze przepływa nawet wtedy, gdy jej nie określasz. Zasadniczo dokumentacja jest całkowicie błędna. Czy istnieje opis tego, co ExecutionContext robi w rzeczywistości i dlaczego jest przydatny?

Odpowiedz

8

To dość myląca dokumentacja. Nie mogę odpowiedzieć na szersze pytanie, ale mogę ci powiedzieć, dlaczego nie płynie.

Jeśli spojrzeć na źródła Thread.Start, ostatecznie wzywa się do:

[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); 
    } 

zauważyć, że wyraźnie przechodzi ExecutionContext.CaptureOptions.IgnoreSyncCtx domyślnie. Przekazuje również CallContext.Principal niezależnie od ExecutionContext.SuppressFlow(). Tak więc wyjaśnia, dlaczego widzisz to, co widzisz, ale nie wtedy, kiedy może być użyteczne lub dlaczego dokumenty są błędne!