1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System
.Collections
.Generic
;
6 using System
.Diagnostics
;
7 using System
.Diagnostics
.CodeAnalysis
;
8 using System
.Globalization
;
9 using System
.Runtime
.ConstrainedExecution
;
10 using System
.Security
.Principal
;
12 namespace System
.Threading
14 public sealed partial class Thread
: CriticalFinalizerObject
16 private static AsyncLocal
<IPrincipal
?>? s_asyncLocalPrincipal
;
19 private static Thread
? t_currentThread
;
21 public Thread(ThreadStart start
)
26 throw new ArgumentNullException(nameof(start
));
32 public Thread(ThreadStart start
, int maxStackSize
)
37 throw new ArgumentNullException(nameof(start
));
41 throw new ArgumentOutOfRangeException(nameof(maxStackSize
), SR
.ArgumentOutOfRange_NeedNonNegNum
);
44 Create(start
, maxStackSize
);
47 public Thread(ParameterizedThreadStart start
)
52 throw new ArgumentNullException(nameof(start
));
58 public Thread(ParameterizedThreadStart start
, int maxStackSize
)
63 throw new ArgumentNullException(nameof(start
));
67 throw new ArgumentOutOfRangeException(nameof(maxStackSize
), SR
.ArgumentOutOfRange_NeedNonNegNum
);
70 Create(start
, maxStackSize
);
73 private void RequireCurrentThread()
75 if (this != CurrentThread
)
77 throw new InvalidOperationException(SR
.Thread_Operation_RequiresCurrentThread
);
81 private void SetCultureOnUnstartedThread(CultureInfo
value, bool uiCulture
)
85 throw new ArgumentNullException(nameof(value));
87 if ((ThreadState
& ThreadState
.Unstarted
) == 0)
89 throw new InvalidOperationException(SR
.Thread_Operation_RequiresCurrentThread
);
91 SetCultureOnUnstartedThreadNoCheck(value, uiCulture
);
94 partial void ThreadNameChanged(string? value);
96 public CultureInfo CurrentCulture
100 RequireCurrentThread();
101 return CultureInfo
.CurrentCulture
;
105 if (this != CurrentThread
)
107 SetCultureOnUnstartedThread(value, uiCulture
: false);
110 CultureInfo
.CurrentCulture
= value;
114 public CultureInfo CurrentUICulture
118 RequireCurrentThread();
119 return CultureInfo
.CurrentUICulture
;
123 if (this != CurrentThread
)
125 SetCultureOnUnstartedThread(value, uiCulture
: true);
128 CultureInfo
.CurrentUICulture
= value;
132 public static IPrincipal
? CurrentPrincipal
136 if (s_asyncLocalPrincipal
is null)
138 CurrentPrincipal
= AppDomain
.CurrentDomain
.GetThreadPrincipal();
140 return s_asyncLocalPrincipal
?.Value
;
144 if (s_asyncLocalPrincipal
is null)
150 Interlocked
.CompareExchange(ref s_asyncLocalPrincipal
, new AsyncLocal
<IPrincipal
?>(), null);
152 s_asyncLocalPrincipal
.Value
= value;
156 public static Thread CurrentThread
=> t_currentThread
?? InitializeCurrentThread();
158 public ExecutionContext
? ExecutionContext
=> ExecutionContext
.Capture();
169 throw new InvalidOperationException(SR
.InvalidOperation_WriteOnce
);
174 ThreadNameChanged(value);
181 throw new PlatformNotSupportedException(SR
.PlatformNotSupported_ThreadAbort
);
184 public void Abort(object? stateInfo
)
186 throw new PlatformNotSupportedException(SR
.PlatformNotSupported_ThreadAbort
);
189 public static void ResetAbort()
191 throw new PlatformNotSupportedException(SR
.PlatformNotSupported_ThreadAbort
);
194 [ObsoleteAttribute("Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. https://go.microsoft.com/fwlink/?linkid=14202", false)]
195 public void Suspend()
197 throw new PlatformNotSupportedException(SR
.PlatformNotSupported_ThreadSuspend
);
200 [ObsoleteAttribute("Thread.Resume has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. https://go.microsoft.com/fwlink/?linkid=14202", false)]
203 throw new PlatformNotSupportedException(SR
.PlatformNotSupported_ThreadSuspend
);
206 // Currently, no special handling is done for critical regions, and no special handling is necessary to ensure thread
207 // affinity. If that changes, the relevant functions would instead need to delegate to RuntimeThread.
208 public static void BeginCriticalRegion() { }
209 public static void EndCriticalRegion() { }
210 public static void BeginThreadAffinity() { }
211 public static void EndThreadAffinity() { }
213 public static LocalDataStoreSlot
AllocateDataSlot() => LocalDataStore
.AllocateSlot();
214 public static LocalDataStoreSlot
AllocateNamedDataSlot(string name
) => LocalDataStore
.AllocateNamedSlot(name
);
215 public static LocalDataStoreSlot
GetNamedDataSlot(string name
) => LocalDataStore
.GetNamedSlot(name
);
216 public static void FreeNamedDataSlot(string name
) => LocalDataStore
.FreeNamedSlot(name
);
217 public static object? GetData(LocalDataStoreSlot slot
) => LocalDataStore
.GetData(slot
);
218 public static void SetData(LocalDataStoreSlot slot
, object? data
) => LocalDataStore
.SetData(slot
, data
);
220 [Obsolete("The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead.", false)]
221 public ApartmentState ApartmentState
225 return GetApartmentState();
229 TrySetApartmentState(value);
233 public void SetApartmentState(ApartmentState state
)
235 if (!TrySetApartmentState(state
))
237 throw GetApartmentStateChangeFailedException();
241 public bool TrySetApartmentState(ApartmentState state
)
245 case ApartmentState
.STA
:
246 case ApartmentState
.MTA
:
247 case ApartmentState
.Unknown
:
251 throw new ArgumentOutOfRangeException(SR
.ArgumentOutOfRange_Enum
, nameof(state
));
254 return TrySetApartmentStateUnchecked(state
);
257 [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
258 public CompressedStack
GetCompressedStack()
260 throw new InvalidOperationException(SR
.Thread_GetSetCompressedStack_NotSupported
);
263 [Obsolete("Thread.SetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
264 public void SetCompressedStack(CompressedStack stack
)
266 throw new InvalidOperationException(SR
.Thread_GetSetCompressedStack_NotSupported
);
269 public static AppDomain
GetDomain() => AppDomain
.CurrentDomain
;
270 public static int GetDomainID() => 1;
271 public override int GetHashCode() => ManagedThreadId
;
272 public void Join() => Join(-1);
273 public bool Join(TimeSpan timeout
) => Join(WaitHandle
.ToTimeoutMilliseconds(timeout
));
274 public static void MemoryBarrier() => Interlocked
.MemoryBarrier();
275 public static void Sleep(TimeSpan timeout
) => Sleep(WaitHandle
.ToTimeoutMilliseconds(timeout
));
277 public static byte VolatileRead(ref byte address
) => Volatile
.Read(ref address
);
278 public static double VolatileRead(ref double address
) => Volatile
.Read(ref address
);
279 public static short VolatileRead(ref short address
) => Volatile
.Read(ref address
);
280 public static int VolatileRead(ref int address
) => Volatile
.Read(ref address
);
281 public static long VolatileRead(ref long address
) => Volatile
.Read(ref address
);
282 public static IntPtr
VolatileRead(ref IntPtr address
) => Volatile
.Read(ref address
);
283 [return: NotNullIfNotNull("address")]
284 public static object? VolatileRead(ref object? address
) => Volatile
.Read(ref address
);
285 [CLSCompliant(false)]
286 public static sbyte VolatileRead(ref sbyte address
) => Volatile
.Read(ref address
);
287 public static float VolatileRead(ref float address
) => Volatile
.Read(ref address
);
288 [CLSCompliant(false)]
289 public static ushort VolatileRead(ref ushort address
) => Volatile
.Read(ref address
);
290 [CLSCompliant(false)]
291 public static uint VolatileRead(ref uint address
) => Volatile
.Read(ref address
);
292 [CLSCompliant(false)]
293 public static ulong VolatileRead(ref ulong address
) => Volatile
.Read(ref address
);
294 [CLSCompliant(false)]
295 public static UIntPtr
VolatileRead(ref UIntPtr address
) => Volatile
.Read(ref address
);
296 public static void VolatileWrite(ref byte address
, byte value) => Volatile
.Write(ref address
, value);
297 public static void VolatileWrite(ref double address
, double value) => Volatile
.Write(ref address
, value);
298 public static void VolatileWrite(ref short address
, short value) => Volatile
.Write(ref address
, value);
299 public static void VolatileWrite(ref int address
, int value) => Volatile
.Write(ref address
, value);
300 public static void VolatileWrite(ref long address
, long value) => Volatile
.Write(ref address
, value);
301 public static void VolatileWrite(ref IntPtr address
, IntPtr
value) => Volatile
.Write(ref address
, value);
302 public static void VolatileWrite([NotNullIfNotNull("value")] ref object? address
, object? value) => Volatile
.Write(ref address
, value);
303 [CLSCompliant(false)]
304 public static void VolatileWrite(ref sbyte address
, sbyte value) => Volatile
.Write(ref address
, value);
305 public static void VolatileWrite(ref float address
, float value) => Volatile
.Write(ref address
, value);
306 [CLSCompliant(false)]
307 public static void VolatileWrite(ref ushort address
, ushort value) => Volatile
.Write(ref address
, value);
308 [CLSCompliant(false)]
309 public static void VolatileWrite(ref uint address
, uint value) => Volatile
.Write(ref address
, value);
310 [CLSCompliant(false)]
311 public static void VolatileWrite(ref ulong address
, ulong value) => Volatile
.Write(ref address
, value);
312 [CLSCompliant(false)]
313 public static void VolatileWrite(ref UIntPtr address
, UIntPtr
value) => Volatile
.Write(ref address
, value);
316 /// Manages functionality required to support members of <see cref="Thread"/> dealing with thread-local data
318 private static class LocalDataStore
320 private static Dictionary
<string, LocalDataStoreSlot
>? s_nameToSlotMap
;
322 public static LocalDataStoreSlot
AllocateSlot()
324 return new LocalDataStoreSlot(new ThreadLocal
<object?>());
327 private static Dictionary
<string, LocalDataStoreSlot
> EnsureNameToSlotMap()
329 Dictionary
<string, LocalDataStoreSlot
>? nameToSlotMap
= s_nameToSlotMap
;
330 if (nameToSlotMap
!= null)
332 return nameToSlotMap
;
335 nameToSlotMap
= new Dictionary
<string, LocalDataStoreSlot
>();
336 return Interlocked
.CompareExchange(ref s_nameToSlotMap
, nameToSlotMap
, null) ?? nameToSlotMap
;
339 public static LocalDataStoreSlot
AllocateNamedSlot(string name
)
341 LocalDataStoreSlot slot
= AllocateSlot();
342 Dictionary
<string, LocalDataStoreSlot
> nameToSlotMap
= EnsureNameToSlotMap();
345 nameToSlotMap
.Add(name
, slot
);
350 public static LocalDataStoreSlot
GetNamedSlot(string name
)
352 Dictionary
<string, LocalDataStoreSlot
> nameToSlotMap
= EnsureNameToSlotMap();
355 LocalDataStoreSlot
? slot
;
356 if (!nameToSlotMap
.TryGetValue(name
, out slot
))
358 slot
= AllocateSlot();
359 nameToSlotMap
[name
] = slot
;
365 public static void FreeNamedSlot(string name
)
367 Dictionary
<string, LocalDataStoreSlot
> nameToSlotMap
= EnsureNameToSlotMap();
370 nameToSlotMap
.Remove(name
);
374 private static ThreadLocal
<object?> GetThreadLocal(LocalDataStoreSlot slot
)
378 throw new ArgumentNullException(nameof(slot
));
381 Debug
.Assert(slot
.Data
!= null);
385 public static object? GetData(LocalDataStoreSlot slot
)
387 return GetThreadLocal(slot
).Value
;
390 public static void SetData(LocalDataStoreSlot slot
, object? value)
392 GetThreadLocal(slot
).Value
= value;