Как на самом деле работает.NET ExecutionContext?

Я пытаюсь выяснить, как на самом деле работает 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 ответ

Решение

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

Другие вопросы по тегам