2012-03-22 11 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!

Powiązane problemy