Как на самом деле работает .NET ExecutionContext? - PullRequest
7 голосов
/ 22 марта 2012

Я пытаюсь выяснить, как ExecutionContext действительно работает в версии 4.0 и выше .NET Framework.В документации говорится, что управляемый принцип, синхронизация, языковой стандарт и пользовательский контекст передаются в новый поток при использовании 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 делает в реальности и почему это полезно?

1 Ответ

9 голосов
/ 22 марта 2012

Это довольно обманчивая документация.Я не могу ответить на более широкий вопрос вашего вопроса, но я могу сказать вам, почему 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 по умолчанию.Он также передает CallContext.Principal независимо от ExecutionContext.SuppressFlow ().Итак, это объясняет, почему вы видите то, что видите, а не когда это может быть полезно, или почему документы выложены неверно!

...