3

It is written in the docs:

When the thread pool reuses a thread, it does not clear the data in thread local storage or in fields that are marked with the ThreadStaticAttribute attribute. Therefore, when a method examines thread local storage or fields that are marked with the ThreadStaticAttribute attribute, the values it finds might be left over from an earlier use of the thread pool thread.

Yet it is said nothing about execution context. How can I check whether ExecutionContext is cleared?

Pavel Voronin
  • 13,503
  • 7
  • 71
  • 137
  • This is an imagined problem, not a real one. There is no mechanism to discover TLS associated with a thread. Finding the ExecutionContext back is of course never a problem. – Hans Passant Jul 01 '14 at 10:34
  • @HansPassant Why imagined? If I try to get a context data and find it then logic session is set up somewhere up the call stack. Otherwise I need to set this data. If context is not cleared I can treat this situation incorrectly. – Pavel Voronin Jul 01 '14 at 12:12
  • .NET is heavily invested in flowing the execution context from the originating thread to the TP thread. Very import for CAS and Remoting. It is an imagined problem as long as you can't demonstrate an actual problem. – Hans Passant Jul 01 '14 at 12:18

1 Answers1

2

In short - yes.

  1. SynchronizationContext is not captured.
  2. LogicalCallContext is cleared.

_

using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;

namespace Tests
{
    [TestFixture]
    public class ExecutionContextFlowTest
    {
        [Test]
        public async Task Execute()
        {
            try
            {
                ThreadPool.SetMinThreads(2, 100);
                ThreadPool.SetMaxThreads(2, 100);

                var asyncLocal = new AsyncLocal<bool>();

                await Task.Run(
                    () =>
                        {
                            asyncLocal.Value = true;
                            CallContext.LogicalSetData("test", true);
                        });

                await Task.WhenAll(
                    Enumerable.Range(0, 10).Select(
                        _ => Task.Run(
                            () =>
                                {
                                    Assert.That(asyncLocal.Value, Is.False);
                                    Assert.That(CallContext.LogicalGetData("test"), Is.Null);
                                })).ToArray());
            }
            finally
            {
                ThreadPool.SetMinThreads(10, 100);
                ThreadPool.SetMaxThreads(100, 100);
            }
        }
    }
}

Though I'm not sure about SecurityContext.

[ThreadStatic] and ThreadLocal are not controlled by ExecutionContext (and not cleared).

Also in .NET sources I found a cleanup which replaces ExecutionContext with previous (empty) ones after item execution is completed.

Vlad
  • 3,001
  • 1
  • 22
  • 52