_executionContext = ec;
}
- internal static ContextCallback _ccb = new ContextCallback(ThreadStart_Context);
+ internal static readonly ContextCallback s_threadStartContextCallback = new ContextCallback(ThreadStart_Context);
private static void ThreadStart_Context(object state)
{
ThreadHelper t = (ThreadHelper)state;
+
+ t.InitializeCulture();
+
if (t._start is ThreadStart)
{
((ThreadStart)t._start)();
internal void ThreadStart(object obj)
{
_startArg = obj;
-
- InitializeCulture();
-
+
ExecutionContext context = _executionContext;
if (context != null)
{
- ExecutionContext.RunInternal(context, _ccb, (object)this);
+ ExecutionContext.RunInternal(context, s_threadStartContextCallback, this);
}
else
{
+ InitializeCulture();
((ParameterizedThreadStart)_start)(obj);
}
}
// call back helper
internal void ThreadStart()
{
- InitializeCulture();
-
ExecutionContext context = _executionContext;
if (context != null)
{
- ExecutionContext.RunInternal(context, _ccb, (object)this);
+ ExecutionContext.RunInternal(context, s_threadStartContextCallback, this);
}
else
{
+ InitializeCulture();
((ThreadStart)_start)();
}
}
** ThreadBaseObject to maintain alignment between the two classes.
** DON'T CHANGE THESE UNLESS YOU MODIFY ThreadBaseObject in vm\object.h
=========================================================================*/
- private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
+ internal ExecutionContext m_ExecutionContext; // this call context follows the logical thread
private SynchronizationContext m_SynchronizationContext; // On CoreCLR, this is maintained separately from ExecutionContext
private string m_Name;
}
}
- public ExecutionContext ExecutionContext
- {
- get { return m_ExecutionContext; }
- internal set { m_ExecutionContext = value; }
- }
+ public ExecutionContext ExecutionContext => ExecutionContext.Capture();
internal SynchronizationContext SynchronizationContext
{
public static ExecutionContext Capture()
{
- ExecutionContext executionContext = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext executionContext = Thread.CurrentThread.m_ExecutionContext;
if (executionContext == null)
{
executionContext = Default;
public static AsyncFlowControl SuppressFlow()
{
Thread currentThread = Thread.CurrentThread;
- ExecutionContext executionContext = currentThread.ExecutionContext ?? Default;
+ ExecutionContext executionContext = currentThread.m_ExecutionContext ?? Default;
if (executionContext.m_isFlowSuppressed)
{
throw new InvalidOperationException(SR.InvalidOperation_CannotSupressFlowMultipleTimes);
executionContext = executionContext.ShallowClone(isFlowSuppressed: true);
var asyncFlowControl = new AsyncFlowControl();
- currentThread.ExecutionContext = executionContext;
+ currentThread.m_ExecutionContext = executionContext;
asyncFlowControl.Initialize(currentThread);
return asyncFlowControl;
}
public static void RestoreFlow()
{
Thread currentThread = Thread.CurrentThread;
- ExecutionContext executionContext = currentThread.ExecutionContext;
+ ExecutionContext executionContext = currentThread.m_ExecutionContext;
if (executionContext == null || !executionContext.m_isFlowSuppressed)
{
throw new InvalidOperationException(SR.InvalidOperation_CannotRestoreUnsupressedFlow);
}
- currentThread.ExecutionContext = executionContext.ShallowClone(isFlowSuppressed: false);
+ currentThread.m_ExecutionContext = executionContext.ShallowClone(isFlowSuppressed: false);
}
public static bool IsFlowSuppressed()
{
- ExecutionContext executionContext = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext executionContext = Thread.CurrentThread.m_ExecutionContext;
return executionContext != null && executionContext.m_isFlowSuppressed;
}
// Capture references to Thread Contexts
Thread currentThread0 = Thread.CurrentThread;
Thread currentThread = currentThread0;
- ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext;
+ ExecutionContext previousExecutionCtx0 = currentThread0.m_ExecutionContext;
if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault)
{
// Default is a null ExecutionContext internally
}
ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
- ExecutionContext currentExecutionCtx1 = currentThread1.ExecutionContext;
+ ExecutionContext currentExecutionCtx1 = currentThread1.m_ExecutionContext;
if (currentExecutionCtx1 != previousExecutionCtx1)
{
RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
// Capture references to Thread Contexts
Thread currentThread0 = Thread.CurrentThread;
Thread currentThread = currentThread0;
- ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext;
+ ExecutionContext previousExecutionCtx0 = currentThread0.m_ExecutionContext;
if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault)
{
// Default is a null ExecutionContext internally
}
ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
- ExecutionContext currentExecutionCtx1 = currentThread1.ExecutionContext;
+ ExecutionContext currentExecutionCtx1 = currentThread1.m_ExecutionContext;
if (currentExecutionCtx1 != previousExecutionCtx1)
{
RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
// Enregister threadPoolThread as it crossed EH, and use enregistered variable
Thread currentThread = threadPoolThread;
- ExecutionContext currentExecutionCtx = currentThread.ExecutionContext;
+ ExecutionContext currentExecutionCtx = currentThread.m_ExecutionContext;
// Restore changed SynchronizationContext back to Default
currentThread.SynchronizationContext = null;
Debug.Assert(executionContext != null && !executionContext.m_isDefault, "ExecutionContext argument is Default.");
// Restore Non-Default context
- Thread.CurrentThread.ExecutionContext = executionContext;
+ Thread.CurrentThread.m_ExecutionContext = executionContext;
if (executionContext.HasChangeNotifications)
{
OnValuesChanged(previousExecutionCtx: null, executionContext);
Debug.Assert(contextToRestore != currentContext);
// Restore changed ExecutionContext back to previous
- currentThread.ExecutionContext = contextToRestore;
+ currentThread.m_ExecutionContext = contextToRestore;
if ((currentContext != null && currentContext.HasChangeNotifications) ||
(contextToRestore != null && contextToRestore.HasChangeNotifications))
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ResetThreadPoolThread(Thread currentThread)
{
- ExecutionContext currentExecutionCtx = currentThread.ExecutionContext;
+ ExecutionContext currentExecutionCtx = currentThread.m_ExecutionContext;
// Reset to defaults
currentThread.SynchronizationContext = null;
- currentThread.ExecutionContext = null;
+ currentThread.m_ExecutionContext = null;
if (currentExecutionCtx != null && currentExecutionCtx.HasChangeNotifications)
{
// Reset to defaults again without change notifications in case the Change handler changed the contexts
currentThread.SynchronizationContext = null;
- currentThread.ExecutionContext = null;
+ currentThread.m_ExecutionContext = null;
}
}
internal static void CheckThreadPoolAndContextsAreDefault()
{
Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
- Debug.Assert(Thread.CurrentThread.ExecutionContext == null, "ThreadPool thread not on Default ExecutionContext.");
+ Debug.Assert(Thread.CurrentThread.m_ExecutionContext == null, "ThreadPool thread not on Default ExecutionContext.");
Debug.Assert(Thread.CurrentThread.SynchronizationContext == null, "ThreadPool thread not on Default SynchronizationContext.");
}
internal static object GetLocalValue(IAsyncLocal local)
{
- ExecutionContext current = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext current = Thread.CurrentThread.m_ExecutionContext;
if (current == null)
{
return null;
internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
{
- ExecutionContext current = Thread.CurrentThread.ExecutionContext;
+ ExecutionContext current = Thread.CurrentThread.m_ExecutionContext;
object previousValue = null;
bool hadPreviousValue = false;
}
}
- Thread.CurrentThread.ExecutionContext =
+ Thread.CurrentThread.m_ExecutionContext =
(!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);