// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
namespace System.Threading
{
- internal class ThreadHelper
+ internal sealed class ThreadHelper
{
private Delegate _start;
internal CultureInfo _startCulture;
t.InitializeCulture();
- if (t._start is ThreadStart)
+ if (t._start is ThreadStart threadStart)
{
- ((ThreadStart)t._start)();
+ threadStart();
}
else
{
}
}
- internal struct ThreadHandle
+ internal readonly struct ThreadHandle
{
- private IntPtr m_ptr;
+ private readonly IntPtr _ptr;
internal ThreadHandle(IntPtr pThread)
{
- m_ptr = pThread;
+ _ptr = pThread;
}
}
** ThreadBaseObject to maintain alignment between the two classes.
** DON'T CHANGE THESE UNLESS YOU MODIFY ThreadBaseObject in vm\object.h
=========================================================================*/
- internal ExecutionContext m_ExecutionContext; // this call context follows the logical thread
- private SynchronizationContext m_SynchronizationContext; // On CoreCLR, this is maintained separately from ExecutionContext
+ internal ExecutionContext _executionContext; // this call context follows the logical thread
+ private SynchronizationContext _synchronizationContext; // On CoreCLR, this is maintained separately from ExecutionContext
- private string m_Name;
- private Delegate m_Delegate; // Delegate
+ private string _name;
+ private Delegate _delegate; // Delegate
- private object m_ThreadStartArg;
+ private object _threadStartArg;
/*=========================================================================
** The base implementation of Thread is all native. The following fields
** space so the thread object may be allocated. DON'T CHANGE THESE UNLESS
** YOU MODIFY ThreadBaseObject in vm\object.h
=========================================================================*/
-#pragma warning disable 169
-#pragma warning disable 414 // These fields are not used from managed.
+#pragma warning disable 169 // These fields are not used from managed.
// IntPtrs need to be together, and before ints, because IntPtrs are 64-bit
- // fields on 64-bit platforms, where they will be sorted together.
+ // fields on 64-bit platforms, where they will be sorted together.
- private IntPtr DONT_USE_InternalThread; // Pointer
- private int m_Priority; // INT32
+ private IntPtr _DONT_USE_InternalThread; // Pointer
+ private int _priority; // INT32
// The following field is required for interop with the VS Debugger
// Prior to making any changes to this field, please reach out to the VS Debugger
// team to make sure that your changes are not going to prevent the debugger
// from working.
- private int _managedThreadId; // INT32
-
-#pragma warning restore 414
+ private int _managedThreadId; // INT32
#pragma warning restore 169
[ThreadStatic]
private static Thread t_currentThread;
- // Adding an empty default ctor for annotation purposes
- internal Thread() { }
+ private Thread() { }
- /*=========================================================================
- ** Creates a new Thread object which will begin execution at
- ** start.ThreadStart on a new thread when the Start method is called.
- **
- ** Exceptions: ArgumentNullException if start == null.
- =========================================================================*/
- private void Create(ThreadStart start)
- {
- SetStartHelper((Delegate)start, 0); //0 will setup Thread with default stackSize
- }
+ private void Create(ThreadStart start) =>
+ SetStartHelper((Delegate)start, 0); // 0 will setup Thread with default stackSize
- private void Create(ThreadStart start, int maxStackSize)
- {
+ private void Create(ThreadStart start, int maxStackSize) =>
SetStartHelper((Delegate)start, maxStackSize);
- }
- private void Create(ParameterizedThreadStart start)
- {
+ private void Create(ParameterizedThreadStart start) =>
SetStartHelper((Delegate)start, 0);
- }
- private void Create(ParameterizedThreadStart start, int maxStackSize)
- {
+ private void Create(ParameterizedThreadStart start, int maxStackSize) =>
SetStartHelper((Delegate)start, maxStackSize);
- }
public extern int ManagedThreadId
{
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
get;
}
- // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+ /// <summary>Returns handle for interop with EE. The handle is guaranteed to be non-null.</summary>
internal ThreadHandle GetNativeHandle()
{
- IntPtr thread = DONT_USE_InternalThread;
+ IntPtr thread = _DONT_USE_InternalThread;
- // This should never happen under normal circumstances. m_assembly is always assigned before it is handed out to the user.
- // There are ways how to create an uninitialized objects through remoting, etc. Avoid AVing in the EE by throwing a nice
- // exception here.
+ // This should never happen under normal circumstances.
if (thread == IntPtr.Zero)
+ {
throw new ArgumentException(null, SR.Argument_InvalidHandle);
+ }
return new ThreadHandle(thread);
}
-
- /*=========================================================================
- ** Spawns off a new thread which will begin executing at the ThreadStart
- ** method on the IThreadable interface passed in the constructor. Once the
- ** thread is dead, it cannot be restarted with another call to Start.
- **
- ** Exceptions: ThreadStateException if the thread has already been started.
- =========================================================================*/
+ /// <summary>
+ /// Spawns off a new thread which will begin executing at the ThreadStart
+ /// method on the IThreadable interface passed in the constructor. Once the
+ /// thread is dead, it cannot be restarted with another call to Start.
+ /// </summary>
public void Start(object parameter)
{
- //In the case of a null delegate (second call to start on same thread)
- // StartInternal method will take care of the error reporting
- if (m_Delegate is ThreadStart)
+ // In the case of a null delegate (second call to start on same thread)
+ // StartInternal method will take care of the error reporting.
+ if (_delegate is ThreadStart)
{
- //We expect the thread to be setup with a ParameterizedThreadStart
- // if this constructor is called.
- //If we got here then that wasn't the case
+ // We expect the thread to be setup with a ParameterizedThreadStart if this Start is called.
throw new InvalidOperationException(SR.InvalidOperation_ThreadWrongThreadStart);
}
- m_ThreadStartArg = parameter;
+
+ _threadStartArg = parameter;
Start();
}
// Attach current thread's security principal object to the new
// thread. Be careful not to bind the current thread to a principal
// if it's not already bound.
- if (m_Delegate != null)
+ if (_delegate != null)
{
// If we reach here with a null delegate, something is broken. But we'll let the StartInternal method take care of
// reporting an error. Just make sure we don't try to dereference a null delegate.
- ThreadHelper t = (ThreadHelper)(m_Delegate.Target);
+ ThreadHelper t = (ThreadHelper)_delegate.Target;
ExecutionContext ec = ExecutionContext.Capture();
t.SetExecutionContextHelper(ec);
}
private void SetCultureOnUnstartedThreadNoCheck(CultureInfo value, bool uiCulture)
{
- Debug.Assert(m_Delegate != null);
+ Debug.Assert(_delegate != null);
- ThreadHelper t = (ThreadHelper)(m_Delegate.Target);
+ ThreadHelper t = (ThreadHelper)(_delegate.Target);
if (uiCulture)
{
t._startUICulture = value;
internal SynchronizationContext SynchronizationContext
{
- get { return m_SynchronizationContext; }
- set { m_SynchronizationContext = value; }
+ get => _synchronizationContext;
+ set => _synchronizationContext = value;
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
private extern void StartInternal();
-
- // Helper method to get a logical thread ID for StringBuilder (for
- // correctness) and for FileStream's async code path (for perf, to
- // avoid creating a Thread instance).
+ // Invoked by VM. Helper method to get a logical thread ID for StringBuilder (for
+ // correctness) and for FileStream's async code path (for perf, to avoid creating
+ // a Thread instance).
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- internal static extern IntPtr InternalGetCurrentThread();
+ private static extern IntPtr InternalGetCurrentThread();
- /*=========================================================================
- ** Suspends the current thread for timeout milliseconds. If timeout == 0,
- ** forces the thread to give up the remainder of its timeslice. If timeout
- ** == Timeout.Infinite, no timeout will occur.
- **
- ** Exceptions: ArgumentException if timeout < -1 (Timeout.Infinite).
- ** ThreadInterruptedException if the thread is interrupted while sleeping.
- =========================================================================*/
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ /// <summary>
+ /// Suspends the current thread for timeout milliseconds. If timeout == 0,
+ /// forces the thread to give up the remainder of its timeslice. If timeout
+ /// == Timeout.Infinite, no timeout will occur.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void SleepInternal(int millisecondsTimeout);
- public static void Sleep(int millisecondsTimeout)
- {
- SleepInternal(millisecondsTimeout);
- }
-
- /* wait for a length of time proportional to 'iterations'. Each iteration is should
- only take a few machine instructions. Calling this API is preferable to coding
- a explicit busy loop because the hardware can be informed that it is busy waiting. */
+ public static void Sleep(int millisecondsTimeout) => SleepInternal(millisecondsTimeout);
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ /// <summary>
+ /// Wait for a length of time proportional to 'iterations'. Each iteration is should
+ /// only take a few machine instructions. Calling this API is preferable to coding
+ /// a explicit busy loop because the hardware can be informed that it is busy waiting.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.InternalCall)]
private static extern void SpinWaitInternal(int iterations);
- public static void SpinWait(int iterations)
- {
- SpinWaitInternal(iterations);
- }
+ public static void SpinWait(int iterations) => SpinWaitInternal(iterations);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern bool YieldInternal();
- public static bool Yield()
- {
- return YieldInternal();
- }
+ public static bool Yield() => YieldInternal();
public static Thread CurrentThread => t_currentThread ?? InitializeCurrentThread();
[MethodImpl(MethodImplOptions.NoInlining)]
- private static Thread InitializeCurrentThread()
- {
- return (t_currentThread = GetCurrentThreadNative());
- }
+ private static Thread InitializeCurrentThread() => (t_currentThread = GetCurrentThreadNative());
- [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
private static extern Thread GetCurrentThreadNative();
private void SetStartHelper(Delegate start, int maxStackSize)
{
Debug.Assert(maxStackSize >= 0);
- ThreadHelper threadStartCallBack = new ThreadHelper(start);
+ var threadStartCallBack = new ThreadHelper(start);
if (start is ThreadStart)
{
SetStart(new ThreadStart(threadStartCallBack.ThreadStart), maxStackSize);
}
}
- /*=========================================================================
- ** PRIVATE Sets the IThreadable interface for the thread. Assumes that
- ** start != null.
- =========================================================================*/
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ /// <summary>Sets the IThreadable interface for the thread. Assumes that start != null.</summary>
+ [MethodImpl(MethodImplOptions.InternalCall)]
private extern void SetStart(Delegate start, int maxStackSize);
- /*=========================================================================
- ** Clean up the thread when it goes away.
- =========================================================================*/
- ~Thread()
- {
- // Delegate to the unmanaged portion.
- InternalFinalize();
- }
+ /// <summary>Clean up the thread when it goes away.</summary>
+ ~Thread() => InternalFinalize(); // Delegate to the unmanaged portion.
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
private extern void InternalFinalize();
#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
private extern void StartupSetApartmentStateInternal();
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
- // Retrieves the name of the thread.
- //
+ /// <summary>Retrieves the name of the thread.</summary>
public string Name
{
- get
- {
- return m_Name;
- }
+ get => _name;
set
{
lock (this)
{
- if (m_Name != null)
+ if (_name != null)
+ {
throw new InvalidOperationException(SR.InvalidOperation_WriteOnce);
- m_Name = value;
+ }
+
+ _name = value;
InformThreadNameChange(GetNativeHandle(), value, (value != null) ? value.Length : 0);
}
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void InformThreadNameChange(ThreadHandle t, string name, int len);
- /*=========================================================================
- ** Returns true if the thread has been started and is not dead.
- =========================================================================*/
+ /// <summary>Returns true if the thread has been started and is not dead.</summary>
public extern bool IsAlive
{
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}
- /*=========================================================================
- ** Return whether or not this thread is a background thread. Background
- ** threads do not affect when the Execution Engine shuts down.
- **
- ** Exceptions: ThreadStateException if the thread is dead.
- =========================================================================*/
+ /// <summary>
+ /// Return whether or not this thread is a background thread. Background
+ /// threads do not affect when the Execution Engine shuts down.
+ /// </summary>
public bool IsBackground
{
- get { return IsBackgroundNative(); }
- set { SetBackgroundNative(value); }
+ get => IsBackgroundNative();
+ set => SetBackgroundNative(value);
}
[MethodImpl(MethodImplOptions.InternalCall)]
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void SetBackgroundNative(bool isBackground);
- /*=========================================================================
- ** Returns true if the thread is a threadpool thread.
- =========================================================================*/
+ /// <summary>Returns true if the thread is a threadpool thread.</summary>
public extern bool IsThreadPoolThread
{
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}
- /*=========================================================================
- ** Returns the priority of the thread.
- **
- ** Exceptions: ThreadStateException if the thread is dead.
- =========================================================================*/
+ /// <summary>Returns the priority of the thread.</summary>
public ThreadPriority Priority
{
- get { return (ThreadPriority)GetPriorityNative(); }
- set { SetPriorityNative((int)value); }
+ get => (ThreadPriority)GetPriorityNative();
+ set => SetPriorityNative((int)value);
}
[MethodImpl(MethodImplOptions.InternalCall)]
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void SetPriorityNative(int priority);
- /*=========================================================================
- ** Returns the operating system identifier for the current thread.
- =========================================================================*/
- internal static ulong CurrentOSThreadId
- {
- get
- {
- return GetCurrentOSThreadId();
- }
- }
+ /// <summary>Returns the operating system identifier for the current thread.</summary>
+ internal static ulong CurrentOSThreadId => GetCurrentOSThreadId();
[DllImport(JitHelpers.QCall)]
private static extern ulong GetCurrentOSThreadId();
- /*=========================================================================
- ** Return the thread state as a consistent set of bits. This is more
- ** general then IsAlive or IsBackground.
- =========================================================================*/
- public ThreadState ThreadState
- {
- get { return (ThreadState)GetThreadStateNative(); }
- }
+ /// <summary>
+ /// Return the thread state as a consistent set of bits. This is more
+ /// general then IsAlive or IsBackground.
+ /// </summary>
+ public ThreadState ThreadState => (ThreadState)GetThreadStateNative();
[MethodImpl(MethodImplOptions.InternalCall)]
private extern int GetThreadStateNative();
- public ApartmentState GetApartmentState()
- {
+ public ApartmentState GetApartmentState() =>
#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
- return (ApartmentState)GetApartmentStateNative();
+ (ApartmentState)GetApartmentStateNative();
#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT
- Debug.Assert(false); // the Thread class in CoreFX should have handled this case
- return ApartmentState.MTA;
+ ApartmentState.MTA;
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
- }
- /*=========================================================================
- ** An unstarted thread can be marked to indicate that it will host a
- ** single-threaded or multi-threaded apartment.
- =========================================================================*/
- public bool TrySetApartmentStateUnchecked(ApartmentState state)
- {
+ /// <summary>
+ /// An unstarted thread can be marked to indicate that it will host a
+ /// single-threaded or multi-threaded apartment.
+ /// </summary>
+ public bool TrySetApartmentStateUnchecked(ApartmentState state) =>
#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
- return SetApartmentStateHelper(state, false);
+ SetApartmentStateHelper(state, false);
#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT
- Debug.Assert(false); // the Thread class in CoreFX should have handled this case
- return false;
+ false;
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
- }
#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
internal bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch)
// report the thread as implicitly in the MTA if any
// other thread in the process is CoInitialized.
if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA))
+ {
return true;
+ }
if (retState != state)
+ {
return false;
+ }
return true;
}
}
}
- [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
private static extern int GetCurrentProcessorNumber();
// The upper bits of t_currentProcessorIdCache are the currentProcessorId. The lower bits of
{
int currentProcessorIdCache = t_currentProcessorIdCache--;
if ((currentProcessorIdCache & ProcessorIdCacheCountDownMask) == 0)
+ {
return RefreshCurrentProcessorId();
+ }
+
return (currentProcessorIdCache >> ProcessorIdCacheShift);
}
// called internally from the ThreadPool in NotifyWorkItemComplete.
}
} // End of class Thread
-
- // declaring a local var of this enum type and passing it by ref into a function that needs to do a
- // stack crawl will both prevent inlining of the callee and pass an ESP point to stack crawl to
- // Declaring these in EH clauses is illegal; they must declared in the main method body
- internal enum StackCrawlMark
- {
- LookForMe = 0,
- LookForMyCaller = 1,
- LookForMyCallersCaller = 2,
- LookForThread = 3
- }
}
public static ExecutionContext Capture()
{
- ExecutionContext executionContext = Thread.CurrentThread.m_ExecutionContext;
+ ExecutionContext executionContext = Thread.CurrentThread._executionContext;
if (executionContext == null)
{
executionContext = Default;
public static AsyncFlowControl SuppressFlow()
{
Thread currentThread = Thread.CurrentThread;
- ExecutionContext executionContext = currentThread.m_ExecutionContext ?? Default;
+ ExecutionContext executionContext = currentThread._executionContext ?? Default;
if (executionContext.m_isFlowSuppressed)
{
throw new InvalidOperationException(SR.InvalidOperation_CannotSupressFlowMultipleTimes);
executionContext = executionContext.ShallowClone(isFlowSuppressed: true);
var asyncFlowControl = new AsyncFlowControl();
- currentThread.m_ExecutionContext = executionContext;
+ currentThread._executionContext = executionContext;
asyncFlowControl.Initialize(currentThread);
return asyncFlowControl;
}
public static void RestoreFlow()
{
Thread currentThread = Thread.CurrentThread;
- ExecutionContext executionContext = currentThread.m_ExecutionContext;
+ ExecutionContext executionContext = currentThread._executionContext;
if (executionContext == null || !executionContext.m_isFlowSuppressed)
{
throw new InvalidOperationException(SR.InvalidOperation_CannotRestoreUnsupressedFlow);
}
- currentThread.m_ExecutionContext = executionContext.ShallowClone(isFlowSuppressed: false);
+ currentThread._executionContext = executionContext.ShallowClone(isFlowSuppressed: false);
}
public static bool IsFlowSuppressed()
{
- ExecutionContext executionContext = Thread.CurrentThread.m_ExecutionContext;
+ ExecutionContext executionContext = Thread.CurrentThread._executionContext;
return executionContext != null && executionContext.m_isFlowSuppressed;
}
// Capture references to Thread Contexts
Thread currentThread0 = Thread.CurrentThread;
Thread currentThread = currentThread0;
- ExecutionContext previousExecutionCtx0 = currentThread0.m_ExecutionContext;
+ ExecutionContext previousExecutionCtx0 = currentThread0._executionContext;
if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault)
{
// Default is a null ExecutionContext internally
}
ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
- ExecutionContext currentExecutionCtx1 = currentThread1.m_ExecutionContext;
+ ExecutionContext currentExecutionCtx1 = currentThread1._executionContext;
if (currentExecutionCtx1 != previousExecutionCtx1)
{
RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
// Capture references to Thread Contexts
Thread currentThread0 = Thread.CurrentThread;
Thread currentThread = currentThread0;
- ExecutionContext previousExecutionCtx0 = currentThread0.m_ExecutionContext;
+ ExecutionContext previousExecutionCtx0 = currentThread0._executionContext;
if (previousExecutionCtx0 != null && previousExecutionCtx0.m_isDefault)
{
// Default is a null ExecutionContext internally
}
ExecutionContext previousExecutionCtx1 = previousExecutionCtx;
- ExecutionContext currentExecutionCtx1 = currentThread1.m_ExecutionContext;
+ ExecutionContext currentExecutionCtx1 = currentThread1._executionContext;
if (currentExecutionCtx1 != previousExecutionCtx1)
{
RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
// Enregister threadPoolThread as it crossed EH, and use enregistered variable
Thread currentThread = threadPoolThread;
- ExecutionContext currentExecutionCtx = currentThread.m_ExecutionContext;
+ ExecutionContext currentExecutionCtx = currentThread._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.m_ExecutionContext = executionContext;
+ Thread.CurrentThread._executionContext = executionContext;
if (executionContext.HasChangeNotifications)
{
OnValuesChanged(previousExecutionCtx: null, executionContext);
Debug.Assert(contextToRestore != currentContext);
// Restore changed ExecutionContext back to previous
- currentThread.m_ExecutionContext = contextToRestore;
+ currentThread._executionContext = contextToRestore;
if ((currentContext != null && currentContext.HasChangeNotifications) ||
(contextToRestore != null && contextToRestore.HasChangeNotifications))
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ResetThreadPoolThread(Thread currentThread)
{
- ExecutionContext currentExecutionCtx = currentThread.m_ExecutionContext;
+ ExecutionContext currentExecutionCtx = currentThread._executionContext;
// Reset to defaults
currentThread.SynchronizationContext = null;
- currentThread.m_ExecutionContext = null;
+ currentThread._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.m_ExecutionContext = null;
+ currentThread._executionContext = null;
}
}
internal static void CheckThreadPoolAndContextsAreDefault()
{
Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
- Debug.Assert(Thread.CurrentThread.m_ExecutionContext == null, "ThreadPool thread not on Default ExecutionContext.");
+ Debug.Assert(Thread.CurrentThread._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.m_ExecutionContext;
+ ExecutionContext current = Thread.CurrentThread._executionContext;
if (current == null)
{
return null;
internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
{
- ExecutionContext current = Thread.CurrentThread.m_ExecutionContext;
+ ExecutionContext current = Thread.CurrentThread._executionContext;
object previousValue = null;
bool hadPreviousValue = false;
}
}
- Thread.CurrentThread.m_ExecutionContext =
+ Thread.CurrentThread._executionContext =
(!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);